如何使用正则表达式获取 Rails 迁移文件中的命令?

问题描述 投票:0回答:1

我正在尝试使用正则表达式,基于特定迁移命令以数组形式从 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 之间,但不起作用。有人可以帮助我吗?

ruby-on-rails regex ruby migration
1个回答
0
投票

我认为在扫描文件内容之前,您可以将逗号后面的所有换行符替换为空格:

migration_content = migration_content.gsub(/,\s*\R/, ', ')

也许还可以使用

gsub(/\(\s*\R/, '(')
来替换代码行以
(

结尾的多行函数调用
© www.soinside.com 2019 - 2024. All rights reserved.