我正在开展一项rake任务,可以更改某些页面的元标记。这些标签在控制器中定义。 rake任务是打开控制器文件,在其中找到包含短语“@meta_tag”的任何行,然后按照replace_line(line)方法重写该行。当我运行rake任务时,我没有收到任何错误,但它也没有进行任何更改。
我认为我的问题出在'r +'行。我是否需要在一行中打开文件并在另一行代码中写入?
require 'rake'
namespace :meta_tags do
desc 'changes the meta tags'
task :update => :environment do
regex = /@meta_tag/
found = false
file = File.open('app/controllers/site_controller.rb', 'r+')
file.each_line do |line|
replace_line(line) if(found)
found = true if(line =~ regex)
end
end
def replace_line(line)
meta_tags = MetaTag.all.map { |tag| tag["tag"] }
new_tag = meta_tags.sample(1)[0]
line = "@meta_tag = #{new_tag}"
end
end
如果你看到我做错了什么,请告诉我。
答案 0 :(得分:1)
嗯,你实际上并没有在任何地方写入文件。 each_line
正如它所说的那样,它遍历文件中的每一行(实际上它会读取直到有换行符然后将此行生成到您提供的块)。
但是现在只使用file.write
并不是一个好主意,因为 inplace 文件写入不能像您期望的那样工作。因为文件是基于字节/字符的,所以替换行必须与旧文件一样长。
所以你应该选择正常使用的阅读然后写的做法。此外,您当前的代码会改变后的行
@meta_tag
发生,但您的问题表明这不是什么
你要。
以下是适用于您的情况的示例:
require 'rake'
namespace :meta_tags do
desc 'changes the meta tags'
task :update => :environment do
regex = /@meta_tag/
# only 'r' since you will only read the file,
# although you could use 'r+' and just change the lineno
# back to 0 when finished reading...
file = File.open('app/controllers/site_controller.rb', 'r')
lines = []
file.each_line do |line|
# i don't think you need the found variable,
# it is simple if-then/else
(line =~ regex) ? (lines << replace_line(line)) : (lines << line)
end
file.close
file = File.open('app/controllers/site_controller.rb', 'w')
# you could also join the array beforehand,
# and use one big write-operation,
# i don't know which approach would be faster...
lines.each{|line| file.write line}
file.close
end
def replace_line(line)
meta_tags = MetaTag.all.map { |tag| tag["tag"] }
new_tag = meta_tags.sample(1)[0]
line = "@meta_tag = #{new_tag}\n" # added the newline
end
end