Question

Edited to include SSCE

I have a Proc object which I add to a Hash with other Procs:

ten_percent_discount_over_sixty = Proc.new {
  cart.each { |item| cart_total += item.price }

  if cart_total >= 60.00
    cart_total =- cart_total * 0.1
  end
}

As you can see there is a cart array which contains items. I can't however get my cart instance variable into the scope of this proc. So later when I iterate through all of these rules in another method, I get undefined variable errors.

The point of doing this is that I have various promotional rules (functions) that need to be run on this cart object. It's possible there's a better way to store rules that can be applied iteratively to a objects instance variable.


I have checkout object which contains a cart (an array) of item objects; items have the attributes: code, price and name.

Next I have a Promotion object which holds a hash of promotional rules. This hash contains Proc objects that hold these rules (which are functions that each run on the cart object changing the final price of the cart). Rules maybe added and removed by calling a method and with the name as an argument.

The problem I am having is when I iterate through the hash of promotional rules. I don't know how to get the cart object into the scope of those Proc objects in order to run the functions contained in those Proc objects, changing the cart state.

  1. Do I pass in the cart object when creating the Proc/lambda?
  2. Create a cart instance variable in the Promotion object and set/get it?
  3. Somehow pass in the cart variable within the checkout object?
  4. I'm over-thinking or approaching the problem in an incorrect manner?

The full code is quite long so I'll post a gist below:

https://gist.github.com/3163127

Était-ce utile?

La solution

Your rule procs must accept cart as an argument, act on it, and return modified cart.

cart = {total: 100}

rules = {ten_percent_discount: lambda{|c| c[:total] *= 0.9; c },
  five_percent_discount: lambda{|c| c[:total] *= 0.95; c}}

rules.each do |name, rule|
  cart = rule.call cart.dup
end

cart # => {:total=>85.5}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top