如何制作一个修改文件的生成器。
我正在尝试使它查找文件中的模式,并在其下一行添加某些内容。
Rails的脚手架生成器在向 config/routes.rb
添加路由时会执行此操作。它通过调用一个非常简单的方法来实现:
Rails的scaffold生成器会在添加一条路由到config/routes.rb
时进行这个操作。它会调用一个非常简单的方法:
def gsub_file(relative_destination, regexp, *args, &block)
path = destination_path(relative_destination)
content = File.read(path).gsub(regexp, *args, &block)
File.open(path, 'wb') { |file| file.write(content) }
end
这个方法的作用是将路径/文件作为第一个参数,然后是正则表达式模式、gsub参数和块。这是一个受保护的方法,你需要重新创建才能使用。我不确定是否可以访问destination_path
,所以你可能需要传递准确的路径并跳过任何转换。
要使用gsub_file
,假设您想向用户模型添加标签。以下是如何实现:
line = "class User < ActiveRecord::Base"
gsub_file 'app/models/user.rb', /(#{Regexp.escape(line)})/mi do |match|
"#{match}\n has_many :tags\n"
end
你正在查找文件中的特定行、类的开头,并在下面添加你的has_many
代码。
但要小心,这是最容易出错的添加内容的方式,这也是为什么路由是唯一使用它的地方之一。上面的示例通常会使用mix-in来处理。
我喜欢Jaime的答案。但是,当我开始使用它时,我意识到需要进行一些修改。以下是我正在使用的示例代码:
private
def destination_path(path)
File.join(destination_root, path)
end
def sub_file(relative_file, search_text, replace_text)
path = destination_path(relative_file)
file_content = File.read(path)
unless file_content.include? replace_text
content = file_content.sub(/(#{Regexp.escape(search_text)})/mi, replace_text)
File.open(path, 'wb') { |file| file.write(content) }
end
end
gsub
将替换所有搜索文本的实例;我只需要一个。因此,我使用 sub
。unless
块中。def destination_path()
。 def configure_simplecov
code = "#Simple Coverage\nrequire 'simplecov'\nSimpleCov.start"
sub_file 'spec/spec_helper.rb', search = "ENV[\"RAILS_ENV\"] ||= 'test'", "#{search}\n\n#{code}\n"
sub_file 'features/support/env.rb', search = "require 'cucumber/rails'", "#{search}\n\n#{code}\n"
end
可能有更加优雅和DRY的方法来实现这个功能。我很喜欢Jamie示例中如何添加文本块的方式。希望我的示例增加了更多的功能和错误检查。