class RuboCop::Cop::Rails::DynamicFindBy

This cop checks dynamic `find_by_*` methods. Use `find_by` instead of dynamic method. See. rails.rubystyle.guide#find_by

@example

# bad
User.find_by_name(name)
User.find_by_name_and_email(name)
User.find_by_email!(name)

# good
User.find_by(name: name)
User.find_by(name: name, email: email)
User.find_by!(email: email)

@example AllowedMethods: find_by_sql

# bad
User.find_by_query(users_query)

# good
User.find_by_sql(users_sql)

@example AllowedReceivers: Gem::Specification

# bad
Specification.find_by_name('backend').gem_dir

# good
Gem::Specification.find_by_name('backend').gem_dir

Constants

IGNORED_ARGUMENT_TYPES
METHOD_PATTERN
MSG

Public Instance Methods

on_csend(node)
Alias for: on_send
on_send(node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 42
def on_send(node)
  return if (node.receiver.nil? && !inherit_active_record_base?(node)) || allowed_invocation?(node)

  method_name = node.method_name
  static_name = static_method_name(method_name)
  return unless static_name
  return if node.arguments.any? { |argument| IGNORED_ARGUMENT_TYPES.include?(argument.type) }

  message = format(MSG, static_name: static_name, method: method_name)
  add_offense(node, message: message) do |corrector|
    autocorrect(corrector, node)
  end
end
Also aliased as: on_csend

Private Instance Methods

allowed_invocation?(node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 68
def allowed_invocation?(node)
  allowed_method?(node) || allowed_receiver?(node) ||
    whitelisted?(node)
end
allowed_method?(node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 73
def allowed_method?(node)
  return unless cop_config['AllowedMethods']

  cop_config['AllowedMethods'].include?(node.method_name.to_s)
end
allowed_receiver?(node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 79
def allowed_receiver?(node)
  return unless cop_config['AllowedReceivers'] && node.receiver

  cop_config['AllowedReceivers'].include?(node.receiver.source)
end
autocorrect(corrector, node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 59
def autocorrect(corrector, node)
  keywords = column_keywords(node.method_name)

  return if keywords.size != node.arguments.size

  autocorrect_method_name(corrector, node)
  autocorrect_argument_keywords(corrector, node, keywords)
end
autocorrect_argument_keywords(corrector, node, keywords) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 98
def autocorrect_argument_keywords(corrector, node, keywords)
  keywords.each.with_index do |keyword, idx|
    corrector.insert_before(node.arguments[idx].loc.expression, keyword)
  end
end
autocorrect_method_name(corrector, node) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 93
def autocorrect_method_name(corrector, node)
  corrector.replace(node.loc.selector,
                    static_method_name(node.method_name.to_s))
end
column_keywords(method) click to toggle source
# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 104
def column_keywords(method)
  keyword_string = method.to_s[METHOD_PATTERN, 1]
  keyword_string.split('_and_').map { |keyword| "#{keyword}: " }
end
static_method_name(method_name) click to toggle source

Returns static method name. If code isn't wrong, returns nil

# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 111
def static_method_name(method_name)
  match = METHOD_PATTERN.match(method_name)
  return nil unless match

  match[2] ? 'find_by!' : 'find_by'
end
whitelisted?(node) click to toggle source

config option `WhiteList` will be deprecated soon

# File lib/rubocop/cop/rails/dynamic_find_by.rb, line 86
def whitelisted?(node)
  whitelist_config = cop_config['Whitelist']
  return unless whitelist_config

  whitelist_config.include?(node.method_name.to_s)
end