This probably isn\'t something you should try at home, but for some reason or another I tried to create an array of methods in Ruby.
I started by defining two methods.
What you're storing in your array is the result of calling your methods, not the methods themselves.
def test1
puts "foo!"
end
def test2
puts "bar!"
end
You can store references to the actual methods like this:
> arr = [method(:test1), method(:test2)]
# => [#<Method: Object#test1>, #<Method: Object#test2>]
Later, you can call the referenced methods like this:
> arr.each {|m| m.call }
foo!
bar!
@alestanis explained the reason well. If you were trying to store the methods, then you can do what Lars Haugseth says or you could do the folllowing:
test1 = Proc.new { puts "test!" }
test2 = Proc.new { puts "test2!" }
a = [test1, test2]
This may make your code much more readable.
Here is an irb run.
1.9.3p194 :009 > test1 = Proc.new { puts "test!" }
=> #<Proc:0x00000002798a90@(irb):9>
1.9.3p194 :010 > test2 = Proc.new { puts "test2!" }
=> #<Proc:0x00000002792988@(irb):10>
1.9.3p194 :011 > a = [test1, test2]
=> [#<Proc:0x00000002798a90@(irb):9>, #<Proc:0x00000002792988@(irb):10>]
Your array never contains anything else than two nil values. I tricks you by putting the strings when evaluating. But the return value of each function still is nil.
Here's my two-pennies worth. Building on the solutions already posted, this is an example of a working example. What might be handy for some here is that it includes method arguments and the use of self
(which refers to the instance of the PromotionalRules class when it is instantiated) and the array of symbols, which is neat - I got that from the Ruby docs on the #send method here. Hope this helps someone!
class PromotionalRules
PROMOTIONS = [:lavender_heart_promotion, :ten_percent_discount]
def apply_promotions total, basket
@total = total
if PROMOTIONS.count > 0
PROMOTIONS.each { |promotion| @total = self.send promotion, @total, basket }
end
@total.round(2)
end
def lavender_heart_promotion total, basket
if two_or_more_lavender_hearts? basket
basket.map { |item| total -= 0.75 if item == 001 }
end
total
end
def two_or_more_lavender_hearts? basket
n = 0
basket.each do |item|
n += 1 if item == 001
end
n >= 2
end
def ten_percent_discount total, *arg
if total > 60.00
total = total - total/10
end
total
end
end
Thanks to everyone for their help. I love the open-source nature of coding - threads just get better and better as people iterate over each other's solutions!
If you had a square
method and wanted to create an array with the square values of 2 and 4, you would write
array = [square(2), square(4)]
Here you are doing exactly the same thing, except that your test methods don't return anything and that's why your final array
seems empty (actually, it contains [nil, nil]
).
Your code runs the two methods because you're actually calling the methods when you say "test1" and "test2" - parentheses are optional for ruby method calls.
Since both of your methods just contain a "puts", which returns nil, your resulting array is just an array of two nils.