我正在尝试使用正则表达式,基于特定迁移命令以数组形式从 Rails 迁移文件中获取命令。我的代码在大多数情况下运行良好,但是当存在包含多行代码的命令时,它会损坏并且我无法修复。
示例
class AddMissingUniqueIndices < ActiveRecord::Migration
def self.up
add_index :tags, :name, unique: true
remove_index :taggings, :tag_id
remove_index :taggings, [:taggable_id, :taggable_type, :context]
add_index :taggings,
[:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type],
unique: true, name: 'taggings_idx'
end
def self.down
remove_index :tags, :name
remove_index :taggings, name: 'taggings_idx'
add_index :taggings, :tag_id
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
end
我的目标是返回一个数组,其中分隔的命令作为字符串。我的期望:
[
"add_index :tags, :name, unique: true",
"remove_index :taggings, :tag_id",
"remove_index :taggings, [:taggable_id, :taggable_type, :context]",
"add_index :taggings, [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], unique: true, name: 'taggings_idx'"
]
首先,我分离
change
或 self.up
块(对于旧迁移),然后尝试使用上面的正则表达式代码将每个添加/删除索引命令收集到一个数组中:
migration_content = 'migration file in txt'
@table_name = 'taggings'
regex_pattern = /(add|remove)_index\s+:#{@table_name}.*\w+:\s+?\w+/m
columns_to_process = migration_content.to_enum(:scan, regex_pattern).map { Regexp.last_match.to_s.squish }
puts columns_to_process
=> ["remove_index :taggings, :tag_id remove_index :taggings, [:taggable_id, :taggable_type, :context] add_index :taggings, [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], unique: true"]
如您所见,不起作用,只返回 2 个命令,并且都在同一个字符串中。 这对于内联代码来说效果很好,当用户可以使用像最后一个
self.up
操作这样的块时,我的问题就开始了,特别是这种有很多元素的情况,我无法使正则表达式适应所有情况,也尝试获取所有内容在 add_index/remove_index 或 end 之间,但不起作用。有人可以帮助我吗?
我认为在扫描文件内容之前,您可以将逗号后面的所有换行符替换为空格:
migration_content = migration_content.gsub(/,\s*\R/, ', ')
也许还可以使用
gsub(/\(\s*\R/, '(')
来替换代码行以 (
结尾的多行函数调用