How can I write the conditional: each in ruby ββis more concise?
3 answers
You can use Object#send
to call the method dynamically:
method = items.respond_to?(:find_each) ? :find_each : :each
items.send(method) do |item|
output_item(csv, item)
end
+5
source to share
I would try to make the intent for this thread a little clearer:
iterator = items.is_a?(ActiveRecord::Relation) ? :find_each : :each
items.send(iterator) { |item| output_item(csv, item) }
Which iterator to choose is an implementation detail that can make my business logic difficult to understand. Let's extract the iteration logic into a separate method. The benefit of this extraction is debatable if the general business logic is one liner. This will add more clarity if the original method is longer.
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) }
Now that we are free from the original method, I would expand on the triple if
to improve readability.
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
source to share