2017-05-15 7 views
3

Rubyでこのコードをもっときれいに書く方法がわかりませんか?違いがあるのはイテレータだけです。どのように条件文を書くことができますか?それぞれをより簡潔にルビーに入れますか?

method = items.respond_to?(:find_each) ? :find_each : :each 
items.send(method) do |item| 
    output_item(csv, item) 
end 
+1

「アイテム」はどこから来ていますか、それはさまざまなメソッドにどのように応答しますか? – Stefan

+0

OPのユースケースは分かりませんが、 'items'がActiveRecord :: Relationなら' find_each'に応答します。それが配列の場合、それはできません。おそらくOPには、検索結果が配列に変換される最適化のいくつかのケースがあります。 – moveson

答えて

5

iterator = items.is_a?(ActiveRecord::Relation) ? :find_each : :each 
items.send(iterator) { |item| output_item(csv, item) } 

Wh私のビジネスロジックを理解することをより困難にするかもしれない実装の詳細は、反復子を選ぶことです。反復ロジックを別の方法で抽出しましょう。この抽出の利点は、ビジネスロジック全体が1つのライナーである場合には議論の余地があります。元の方法がもっと長い場合は、より明確になります。

def iterate(relation_or_array, *args, &block) 
    iterator = relation_or_array.is_a?(ActiveRecord::Relation) ? :find_each : :each 
    relation_or_array.send(iterator, *args, &block) 
end 

# main logic 
iterate(items) { |item| output_item(csv, item) } 

今、私たちは元のメソッドの自由だということに、私は読みやすさを向上させるために三元ifを展開するだろう。

def iterate(relation_or_array, *args, &block) 
    if relation_or_array.is_a? ActiveRecord::Relation 
    relation_or_array.find_each(*args, &block) 
    else 
    relation_or_array.each(*args, &block) 
    end 
end 

# main logic 
iterate(items) { |item| output_item(csv, item) } 
+0

ええ、あなたはそれに私を打つ... :) – moveson

2

私はあなたができるとします:

method = items.respond_to?(:find_each) ? :find_each : :each 
items.send(method) { |item| output_item(csv, item) } 
0

私はこのブランチのための意図は少し明確にしようと思いますが、動的にメソッドを呼び出すためにObject#sendを使用することができます

if items.respond_to?(:find_each) 
    items.find_each do |item| 
     output_item(csv, item) 
    end 
    else 
    items.each do |item| 
     output_item(csv, item) 
    end 
    end 
関連する問題