无法访问块中的ActiveRecord mutators

时间:2011-11-12 21:10:19

标签: ruby-on-rails ruby activerecord prawnto

我在Rails控制器中,我正在尝试访问块中的实例变量: 这给出了一个错误,说“没有方法字段1为Nil”:

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

但是,如果我这样做,那么它可行:

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

这是否与块中的ActiveRecord访问器或实例变量有关?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

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