ブロック内のActiveRecordミューテータにアクセスできない

私はRailsコントローラの中にいて、ブロック内のインスタンス変数にアクセスしようとしています。 これは、 "Nilのメソッドフィールド1はありません"というエラーを出します。

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

しかし、私がこれを行うと、それは動作します:

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

これはブロック内のActiveRecordアクセサやインスタンス変数と関係がありますか?

0
ありがとう、私はこのスレッドがより良い答えを持っていると思う:P私はそれが1つにこれらの2つのスレッドをマージする意味がないと思う。
追加された 著者 m33lky,
この質問もあなたの答えになるはずです:ruby block "> stackoverflow.com/questions/5150483/…
追加された 著者 topek,

2 答え

この種の問題は、通常は 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
3
追加された

これは、ブロック内のコードが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

ご覧のとおり、ブロックドキュメントオブジェクトで self として実行されます。 @modelを self のインスタンス変数として見つけようとしますが、これを実行して nil を返すことはできません。ローカル変数 model を使用すると、クロージャのヘルプが表示され、コードが正しく機能しています

1
追加された
また、 my_model = @model のように、インスタンス変数をRubyの変数に変換する方法はありますか?
追加された 著者 m33lky,