【问题标题】:can't access ActiveRecord mutators in a block无法访问块中的 ActiveRecord 修改器
【发布时间】:2011-12-27 19:11:26
【问题描述】:

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

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

但是,如果我这样做,那么它会起作用:

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

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

【问题讨论】:

标签: ruby-on-rails ruby activerecord prawnto


【解决方案1】:

当一个块在不同的上下文中执行时会出现这种问题,通常是通过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

【讨论】:

    【解决方案2】:

    这是因为块内的代码是在 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,你会得到闭包的帮助并且你的代码工作正常

    【讨论】:

    • 另外,有没有一种捷径可以将实例变量转换为 Ruby 中的变量,而不会像使用 my_model = @model 那样浪费一行?
    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多