0

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

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

但是,如果我这样做,那么它可以工作:

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

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

4

2 回答 2

3

当一个块在不同的上下文中执行时会出现这种问题,通常是通过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
于 2011-11-12T21:23:21.503 回答
1

这是因为块内的代码是在 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

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

于 2011-11-12T21:25:22.397 回答