0

我正在执行一项更改某些页面的元标记的 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

如果你看到我做错了什么,请告诉我。

4

1 回答 1

1

好吧,您实际上并没有在任何地方写入文件。each_line就像它所说的那样,它遍历文件中的每一行(实际上它会读取直到有一个换行符,然后将此行生成给您提供的块)。

但是file.write现在使用并不是一个好主意,因为就地文件写入不像您期望的那样工作。因为文件是基于字节/字符的,所以替换行必须与旧行一样长。

因此,您应该遵循通常使用的阅读然后写作的做法。此外,您当前的代码会在 发生@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
于 2012-07-18T19:10:30.697 回答