Rubyでこのコードをもっときれいに書く方法がわかりませんか?違いがあるのはイテレータだけです。どのように条件文を書くことができますか?それぞれをより簡潔にルビーに入れますか?
method = items.respond_to?(:find_each) ? :find_each : :each
items.send(method) do |item|
output_item(csv, item)
end
Rubyでこのコードをもっときれいに書く方法がわかりませんか?違いがあるのはイテレータだけです。どのように条件文を書くことができますか?それぞれをより簡潔にルビーに入れますか?
method = items.respond_to?(:find_each) ? :find_each : :each
items.send(method) do |item|
output_item(csv, item)
end
:
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) }
ええ、あなたはそれに私を打つ... :) – moveson
私はあなたができるとします:
method = items.respond_to?(:find_each) ? :find_each : :each
items.send(method) { |item| output_item(csv, item) }
私はこのブランチのための意図は少し明確にしようと思いますが、動的にメソッドを呼び出すために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
「アイテム」はどこから来ていますか、それはさまざまなメソッドにどのように応答しますか? – Stefan
OPのユースケースは分かりませんが、 'items'がActiveRecord :: Relationなら' find_each'に応答します。それが配列の場合、それはできません。おそらくOPには、検索結果が配列に変換される最適化のいくつかのケースがあります。 – moveson