2009-11-27 6 views
1

J'ai lu this question, mais je ne pouvais pas créer un exemple complet:Enchaînement conditionnelle en rubis

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/étude/ruby ​​/ oop ]% rubis inject_ex.rb
un

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

(NoMethodError)

de inject_ex.rb: 26: dans `chaque '

de inject_ex.rb: 26: dans` inject'

de inject_ex.rb: 26: dans ` »

Répondre

4

Inject passe la valeur de retour du bloc à l'itération suivante. Maintenant, votre obj a la valeur de retour de obj.send(:method_a) après la première itération. Fixez votre inject comme ceci:

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

Vous pouvez utiliser tap aussi:

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

Ou vous pouvez utiliser du robinet pour se débarrasser de cette l:

some.tap{|s|s.method_a if a}.tap{|s|s.method_b if b}.tap{|s|s.method_c if c} 
1

robinet est la méthode ajouter dans ruby ​​1.9.Mais on peut utiliser la méthode return dans Rails dans ruby ​​1.8. Rails code console:

>> 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> 
>>