如何使用 rspec / Rails 5 在 CSV 夹具中编译 ERB?

How to compile ERB in a CSV fixture with rspec / Rails 5?

我想将一些 ERB 编译成 CSV 文件,放在我的规范中。这是 CSV:

(spec/fixtures/files/song_info.csv.erb)

song id,        song_title
<%= song.id %>, Fun Title

在我的测试中,我首先创建了一首歌曲,这样我就可以将它的 id 插入到夹具中,然后加载 CSV。

describe "#update" do
  let(:song) { FactoryGirl.create :song }         # create the instance
  let(:csv) { file_fixture("song_info.csv.erb").read } # load the file

  it "finds a song and adds it's title" do        
    # when I look at csv here, it is just a string with the raw ERB 
  end
end

测试中发生的事情并不重要。问题是,当我检查 csv 的内容时,我发现它只是一个带有原始 ERB(未编译)的字符串。

"song_id, new_song_title, <%= song.id %>, Song Title"

如何强制 ERB 编译? #read 不是正确的 file_fixture 方法吗?这完全是另一回事吗?

注意:我知道还有其他方法可以在没有固定装置的情况下完成此操作,但这是一个微不足道的例子。我只想知道怎么把ERB编译成fixture

您需要创建一个 ERB 实例并对其进行评估:

let(:csv) { ERB.new(file_fixture("song_info.csv.erb").read).result(binding) } # load the file

binding 有点神奇,它会给你一个 Binding class 的实例,它封装了代码中这个特定位置的执行上下文。更多信息:https://ruby-doc.org/core-2.3.0/Binding.html

如果您需要自定义绑定来执行更复杂的操作,您可以创建一个 class 并从那里生成一个绑定,例如:

require 'csv'
require 'erb'

class CustomBinding
  def initialize(first_name, last_name)
    @id = rand(1000)
    @first_name = first_name
    @last_name = last_name
  end

  def get_binding
    binding()
  end
end

template = <<-EOS
"id","first","last"
<%= CSV.generate_line([@id, @first_name, @last_name]) %>
EOS

puts ERB.new(template).result(CustomBinding.new("Yuki", "Matz").get_binding)