class RuboCop::Cop::Performance::Detect
considered unsafe.
own meaning. Correcting ActiveRecord methods with this cop should be
`ActiveRecord` does not implement a ‘detect` method and `find` has its
`ActiveRecord` compatibility:
[].reverse.detect { |item| true }
[].detect { |item| true }
# good
[].find_all { |item| true }.last
[].find_all { |item| true }.first
[].select { |item| true }.last
[].select { |item| true }.first
# bad
@example
and change them to use `detect` instead.
`select.first`, `select.last`, `find_all.first`, and `find_all.last`
This cop is used to identify usages of
def accept_first_call?(receiver, body)
def accept_first_call?(receiver, body) caller, _first_method, args = *receiver # check that we have usual block or block pass return true if body.nil? && (args.nil? || !args.block_pass_type?) lazy?(caller) end
def autocorrect(node)
def autocorrect(node) receiver, first_method = *node replacement = if first_method == :last "reverse.#{preferred_method}" else preferred_method end first_range = receiver.source_range.end.join(node.loc.selector) receiver, _args, _body = *receiver if receiver.block_type? lambda do |corrector| corrector.remove(first_range) corrector.replace(receiver.loc.selector, replacement) end end
def lazy?(node)
def lazy?(node) return false unless node receiver, method, _args = *node method == :lazy && !receiver.nil? end
def on_send(node)
def on_send(node) return if rails_safe_mode? detect_candidate?(node) do |receiver, second_method, args| return unless args.empty? return unless receiver receiver, _args, body = *receiver if receiver.block_type? return if accept_first_call?(receiver, body) register_offense(node, receiver, second_method) end end
def preferred_method
def preferred_method config.for_cop('Style/CollectionMethods') \ ['PreferredMethods']['detect'] || 'detect' end
def register_offense(node, receiver, second_method)
def register_offense(node, receiver, second_method) _caller, first_method, _args = *receiver range = receiver.loc.selector.join(node.loc.selector) message = second_method == :last ? REVERSE_MSG : MSG formatted_message = format(message, prefer: preferred_method, first_method: first_method, second_method: second_method) add_offense(node, location: range, message: formatted_message) end