tags:

views:

59

answers:

3

I have read this question, but I couldn't create a full example:

class Some
  def method_a
    puts "a"
  end

  def method_b
    puts "b"
  end

  def method_c
    puts "c"
  end
end

some = Some.new

a = true
b = true
c = true

l = []
l << :method_a if a
l << :method_b if b
l << :method_c if c

l.inject(some) { |obj, method|
  obj.send(method)
}

[demas @arch.local.net ][~/dev/study/ruby/oop]% ruby inject_ex.rb
a

inject_ex.rb:26:in block in <main>': undefined method method_b' for nil:NilClass

(NoMethodError)

from inject_ex.rb:26:in `each'

from inject_ex.rb:26:in `inject'

from inject_ex.rb:26:in `'

+3  A: 

Inject passes the return value of the block to the next iteration. Now your obj has the return value of obj.send(:method_a) after the first iteration. Fix your inject like this:

l.inject(some) { |obj, method|
  obj.send(method)
  obj
}
hrnt
+2  A: 

You can use tap too:

l.inject(some) do |obj,method|
  obj.tap{|o| o.send(method)}
end

Or you can use tap to get rid of that l:

some.tap{|s|s.method_a if a}.tap{|s|s.method_b if b}.tap{|s|s.method_c if c}
MBO
+1  A: 

tap is the method add in ruby 1.9.But we can use returning method in Rails in ruby 1.8. Rails console code:

>> class Some
>>   def method_a
>>     puts "a"
>>   end
>> 
?>   def method_b
>>     puts "b"
>>   end
>> 
?>   def method_c
>>     puts "c"
>>   end
>> end
=> nil
>> 
?> some = Some.new
=> #<Some:0x2a98c4f938>
>> 
?> a = true
=> true
>> b = true
=> true
>> c = true
=> true
>> 
?> l = []
=> []
>> l << :method_a if a
=> [:method_a]
>> l << :method_b if b
=> [:method_a, :method_b]
>> l << :method_c if c
=> [:method_a, :method_b, :method_c]
>> l.inject(some){|obj, method| returning(obj){|r| r.send method}}
a
b
c
=> #<Some:0x2a98c4f938>
>> 
Hooopo