无法访问块中的ActiveRecord mutators

我在一个Rails控制器中,我试图在一个块中访问我的实例变量:这给出了一个错误,说“没有方法field1 for Nil”:

Prawn::Document.generate("hello.pdf") do @model.field1 end 

但是,如果我这样做,那么它的工作原理:

 my_model = @model Prawn::Document.generate("hello.pdf") do my_model.field1 end 

这可能与块中的ActiveRecord访问器或实例变量有关吗?

这是因为块内的代码是在Prawn :: Document对象的上下文中执行的。 让我们进入这段代码:

 module Prawn class Document def self.generate(filename,options={},&block) pdf = new(options,&block) pdf.render_file(filename) end def initialize(options={},&block) if block block.arity < 1 ? instance_eval(&block) : block[self] end end end end 

如您所见,使用Document对象作为self执行block 。 它试图找到@model作为self实例变量,不能这样做并返回nil 。 如果您使用局部变量model ,您将获得闭包的帮助,并且您的代码正常运行

当块在不同的上下文中执行时,通常通过instance_eval出现这种问题。 那么让我们检查一下代码:

 #lib/prawn/document.rb: Document#initialize if block block.arity < 1 ? instance_eval(&block) : block[self] end 

你有你的instance_eval ,你也可以看到解决方案:传递一个接受文件作为参数的块,你现在可以像往常一样访问实例变量:

 Prawn::Document.generate("hello.pdf") do |doc| @my_model.field1 end