Class: RuboCop::Cop::Sevencop::RailsOrderFieldInOrderOf

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Defined in:
lib/rubocop/cop/sevencop/rails_order_field_in_order_of.rb

Overview

Prefer ‘in_order_of` to MySQL `FIELD` function if possible.

Examples:

# bad
order('FIELD(id, 1, 2, 3)')

# good
in_order_of(:id, [1, 2, 3])

# bad
order(Arel.sql('FIELD(id, 1, 2, 3)'))

# good
in_order_of(:id, [1, 2, 3])

# bad
order('FIELD(id, 1, 2, 3) DESC')

# good
in_order_of(:id, [1, 2, 3]).reverse_order

# bad
order("FIELD(id, #{ids.join(', ')})")

# good
in_order_of(:id, ids)

Cop Safety Information:

  • This cop is unsafe because ‘in_order_of` also adds `WHERE` clause.

    This cop’s autocorrection is unsafe because in the original code the array value is interpolated as literals on SQL query, but after its autocorrection, the value will be now passed directly to in_order_of, which may produce different results.

    For example, the following code is valid where the id column is a integer column:

    ids = %w[1 2 3]
    order("FIELD(id, #{ids.join(', ')})") # "FIELD(id, 1, 2, 3)"
    

    But after its autocorrection, it will be like this:

    ids = %w[1 2 3]
    in_order_of(:id, ids) # We need to change this code as `ids.map(&:to_i)`.
    

    And this code will raise an error because ‘ids` is not an array of Integer but an array of String.

Constant Summary collapse

REGEXP_FIELD_DSTR_HEAD =
/
  \A
  \s*
  field\(
    \s*
    (?<column_name>[^,]+)
    ,\s*
  \z
/ix.freeze
REGEXP_FIELD_DSTR_TAIL =
/
  \A
  \s*
  \)
  \s*
  (?:
    \s+
    (?<order>asc|desc)
  )?
  \z
/ix.freeze
REGEXP_FIELD_STR =
/
  \A
  \s*
  field\(
    \s*
    (?<column_name>[^,]+)
    ,\s*
    (?<values>.+)
    \s*
  \)
  (?:
    \s+
    (?<order>asc|desc)
  )?
  \s*
  \z
/ix.freeze
MSG =
'Prefer `in_order_of` to MySQL `FIELD` function if possible.'
RESTRICT_ON_SEND =
%i[
  order
  reorder
].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ void

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::SendNode)


103
104
105
106
107
108
109
110
111
# File 'lib/rubocop/cop/sevencop/rails_order_field_in_order_of.rb', line 103

def on_send(node)
  return unless bad?(node)

  add_offense(
    convert_to_autocorrected_range(node)
  ) do |corrector|
    autocorrect(corrector, node)
  end
end