Class: RuboCop::Cop::Rails::WhereNot

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
RangeHelp
Defined in:
lib/rubocop/cop/rails/where_not.rb

Overview

Identifies places where manually constructed SQL in ‘where` can be replaced with `where.not(…)`.

Examples:

# bad
User.where('name != ?', 'Gabe')
User.where('name != :name', name: 'Gabe')
User.where('name <> ?', 'Gabe')
User.where('name <> :name', name: 'Gabe')
User.where('name IS NOT NULL')
User.where('name NOT IN (?)', ['john', 'jane'])
User.where('name NOT IN (:names)', names: ['john', 'jane'])
User.where('users.name != :name', name: 'Gabe')

# good
User.where.not(name: 'Gabe')
User.where.not(name: nil)
User.where.not(name: ['john', 'jane'])
User.where.not(users: { name: 'Gabe' })

Constant Summary collapse

MSG =
'Use `%<good_method>s` instead of manually constructing negated SQL in `where`.'
RESTRICT_ON_SEND =
%i[where].freeze
NOT_EQ_ANONYMOUS_RE =

column != ?, column <> ?

/\A([\w.]+)\s+(?:!=|<>)\s+\?\z/.freeze
NOT_IN_ANONYMOUS_RE =

column NOT IN (?)

/\A([\w.]+)\s+NOT\s+IN\s+\(\?\)\z/i.freeze
NOT_EQ_NAMED_RE =

column != :column, column <> :column

/\A([\w.]+)\s+(?:!=|<>)\s+:(\w+)\z/.freeze
NOT_IN_NAMED_RE =

column NOT IN (:column)

/\A([\w.]+)\s+NOT\s+IN\s+\(:(\w+)\)\z/i.freeze
IS_NOT_NULL_RE =

column IS NOT NULL

/\A([\w.]+)\s+IS\s+NOT\s+NULL\z/i.freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object Also known as: on_csend



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rubocop/cop/rails/where_not.rb', line 40

def on_send(node)
  where_method_call?(node) do |template_node, value_node|
    value_node = value_node.first

    range = offense_range(node)

    column, value = extract_column_and_value(template_node, value_node)
    return unless value

    good_method = build_good_method(node.loc.dot&.source, column, value)
    message = format(MSG, good_method: good_method)

    add_offense(range, message: message) do |corrector|
      corrector.replace(range, good_method)
    end
  end
end