Search code examples
rubyproc-object

Referencing a local variable from a Proc defined in another scope


I want to create an instance method which varies its behaviour with return value of another method depending on a implementation of its overwrites in a polymorphic manner.

For example, the following class is assumed to be extended and pricing_rule is supposed to change depending on a product.

class Purchase
  def discount_price
    prices = [100, 200, 300]
    pricing_rule.call
  end
  protected
    def pricing_rule
      Proc.new do
        rate =  prices.size > 2 ? 0.8 : 1
        total = prices.inject(0){|sum, v| sum += v}
        total * rate
      end
    end
end
Purchase.new.discount_price 
#=> undefined local variable or method `prices' for #<Purchase:0xb6fea8c4>

But, I'm getting an undefined local variable error when I run this. Though I understand that the instance of Proc refers to an instance of Purchase, I sometimes encountered similar situations I need to place prices variable into discount_price method. Is there any smarter way to refer to local variable in a caller of a Proc?


Solution

  • I wouldn't expect discount_price's local variables to be accessible inside the Proc returned by pricing_rule. Passing prices in will work:

    class Purchase
      def discount_price
        prices = [100, 200, 300]
        pricing_rule.call prices
      end
      protected
        def pricing_rule
          Proc.new do |prices|
            rate =  prices.size > 2 ? 0.8 : 1
            total = prices.inject(0){|sum, v| sum += v}
            total * rate
          end
        end
    end