class RuboCop::Cop::Rails::FindById

This cop enforces that `ActiveRecord#find` is used instead of `where.take!`, `find_by!`, and `find_by_id!` to retrieve a single record by primary key when you expect it to be found.

@example

# bad
User.where(id: id).take!
User.find_by_id!(id)
User.find_by!(id: id)

# good
User.find(id)

Constants

MSG
RESTRICT_ON_SEND

Public Instance Methods

on_send(node) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 40
def on_send(node)
  where_take?(node) do |where, id_value|
    range = where_take_offense_range(node, where)
    bad_method = build_where_take_bad_method(id_value)

    register_offense(range, id_value, bad_method)
  end

  find_by?(node) do |id_value|
    range = find_by_offense_range(node)
    bad_method = build_find_by_bad_method(node, id_value)

    register_offense(range, id_value, bad_method)
  end
end

Private Instance Methods

build_find_by_bad_method(node, id_value) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 83
def build_find_by_bad_method(node, id_value)
  case node.method_name
  when :find_by_id!
    "find_by_id!(#{id_value.source})"
  when :find_by!
    "find_by!(id: #{id_value.source})"
  end
end
build_good_method(id_value) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 75
def build_good_method(id_value)
  "find(#{id_value.source})"
end
build_where_take_bad_method(id_value) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 79
def build_where_take_bad_method(id_value)
  "where(id: #{id_value.source}).take!"
end
find_by_offense_range(node) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 71
def find_by_offense_range(node)
  range_between(node.loc.selector.begin_pos, node.loc.expression.end_pos)
end
register_offense(range, id_value, bad_method) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 58
def register_offense(range, id_value, bad_method)
  good_method = build_good_method(id_value)
  message = format(MSG, good_method: good_method, bad_method: bad_method)

  add_offense(range, message: message) do |corrector|
    corrector.replace(range, good_method)
  end
end
where_take_offense_range(node, where) click to toggle source
# File lib/rubocop/cop/rails/find_by_id.rb, line 67
def where_take_offense_range(node, where)
  range_between(where.loc.selector.begin_pos, node.loc.expression.end_pos)
end