class RuboCop::Cop::Style::CombinableLoops
end
each_slice(3) { |slice| do_something(slice) }
each_slice(2) { |slice| do_something(slice) }
def method
# good
end
end
do_something_else(item)
do_something(item)
for item in items do
def method
# good
end
end
do_something_else(item)
for item in items do
end
do_something(item)
for item in items do
def method
# bad
end
end
do_something_else(item)
do_something(item)
items.each do |item|
def method
# good
end
end
do_something_else(item)
items.each do |item|
end
do_something(item)
items.each do |item|
def method
# bad
@example
a state that the second loop depends on; these two aren’t combinable.
It is marked as unsafe, because the first loop might modify
will make the code more efficient and more concise.
can be combined into a single loop. It is very likely that combining them
This cop checks for places where multiple consecutive loops over the same data
def collection_looping_method?(node)
def collection_looping_method?(node) method_name = node.send_node.method_name method_name.match?(/^each/) || method_name.match?(/_each$/) end
def on_block(node)
def on_block(node) return unless node.parent&.begin_type? return unless collection_looping_method?(node) add_offense(node) if same_collection_looping?(node, node.left_sibling) end
def on_for(node)
def on_for(node) return unless node.parent&.begin_type? sibling = node.left_sibling add_offense(node) if sibling&.for_type? && node.collection == sibling.collection end
def same_collection_looping?(node, sibling)
def same_collection_looping?(node, sibling) sibling&.block_type? && sibling.send_node.method?(node.method_name) && sibling.send_node.receiver == node.send_node.receiver && sibling.send_node.arguments == node.send_node.arguments end