了解ruby块中的范围

时间:2014-04-17 05:00:38

标签: ruby-on-rails ruby scope prawn

我正在使用Prawn gem写入PDF。我已经开始编写PDF的操作,但我不明白如何以正确的方式使用我的数据。我有:

def download
  @bid = Bid.find(params[:bid_id])
  @title = @bid.bid_title.gsub(/\s+/, "")

  Prawn::Document.generate("#{@title}.pdf") do
    text @bid.client_name
  end
end

在我添加文字的地方,出价为零。如何在下面的块中使用我之前创建的@bid

2 个答案:

答案 0 :(得分:1)

挖掘源代码以了解所有魔法的工作方式通常很有用。

如果我们考虑Prawn source code,我们可以看到方法self.generate(filename, options = {}, &block)中的块被传输到Prawn :: Document.new方法。因此,我们将考虑Prawn :: Document initialize方法。在那里我们可以看到以下代码:

if block
  block.arity < 1 ? instance_eval(&block) : block[self]
end

#arity is a number of block arguments.  
# block[self] is a block.call(self)

如果我们简化Prawn源代码,我们可以模拟这种情况以便更好地理解它:

module Prawn 
  class Document
    def self.generate(filename, &block)
      block.arity < 1 ? instance_eval(&block) : block[self]
    end
  end
end

class A
  def initialize
    @a = 1
  end

  def foo
    qwe = 1
    Prawn::Document.generate("foobar") do 
      p @a
      p qwe
      p instance_variables  
    end
  end
end

A.new.foo

# Output:
     nil # @a
     1   # qwe
     []  # there is no instance_variables

但是如果我们为块提供一个参数,那么将调用generate中的另一个条件(block [self]而不是instance_eval):

module Prawn 
  class Document
    def self.generate(filename, &block)
      block.arity < 1 ? instance_eval(&block) : block[self]
    end
  end
end

class A
  def initialize
    @a = 1
  end

  def foo
    qwe = 1
    Prawn::Document.generate("foobar") do |whatever|
      p @a
      p qwe
      p instance_variables  
    end
  end
end

A.new.foo

# Output
  1     # @a
  1     # qwe
  [:@a] # instance_variables

所以在你的情况下,我认为这段代码会起作用:

def download
  @bid = Bid.find(params[:bid_id])
  @title = @bid.bid_title.gsub(/\s+/, "")

  Prawn::Document.generate("#{@title}.pdf") do |ignored|
    text @bid.client_name
  end
end

def download
  bid = Bid.find(params[:bid_id])
  title = @bid.bid_title.gsub(/\s+/, "")

  Prawn::Document.generate("#{title}.pdf") do
    text bid.client_name
  end
end

答案 1 :(得分:1)

您的问题是Prawn::Document.generate在Prawn :: Document实例的上下文中评估块。这意味着块中的实例变量将被解析为Prawn :: Document对象的实例变量,因为在块的上下文中它是self

要使其工作,请使用局部变量代替(或除了)实例变量。