Class: RuboCop::Cop::Rails::StrongParametersExpect

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector, TargetRailsVersion
Defined in:
lib/rubocop/cop/rails/strong_parameters_expect.rb

Overview

Enforces the use of ‘ActionController::Parameters#expect` as a method for strong parameter handling.

In the following cases, ‘params` is treated as a key that is expected to be passed from the HTTP client, and the cop detects it using the `expect` method.

  • Method calls on ‘params` without comparison methods

  • Passing ‘params` as an argument to finder methods that raise on missing records

  • Strong parameter methods using ‘require` or `permit`

Other cases are not detected, as they are cases where ‘params` may not be passed from the HTTP client.

Examples:


# bad
params[:key].do_something

# good
params.expect(:key).do_something

# bad
Model.find(params[:id])

# good
Model.find(params.expect(:id))

# bad
Model.find_by!(key: params[:key])

# good
Model.find_by!(key: params.expect(:key))

# bad
params.require(:user).permit(:name, :age)
params.permit(user: [:name, :age]).require(:user)

# good
params.expect(user: [:name, :age])

Constant Summary collapse

MSG =
'Use `%<prefer>s` instead.'
RESTRICT_ON_SEND =
%i[[] require permit].freeze
PRESENCE_CHECK_METHODS =
%i[nil? blank? present? presence].freeze
RAISING_FINDER_METHODS =
%i[find find_by! find_sole_by].freeze

Constants included from TargetRailsVersion

TargetRailsVersion::TARGET_GEM_NAME, TargetRailsVersion::USES_REQUIRES_GEM_API

Instance Method Summary collapse

Methods included from TargetRailsVersion

minimum_target_rails_version, support_target_rails_version?

Instance Method Details

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

rubocop:disable Metrics/AbcSize, Metrics/MethodLength



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/rubocop/cop/rails/strong_parameters_expect.rb', line 79

def on_send(node)
  return if part_of_ignored_node?(node)

  if (params_key = params_bracket_access(node))
    register_bracket_access_offense(node, params_key)
    return
  end

  if (permit_method, require_method = params_require_permit(node))
    range = offense_range(require_method, node)
    prefer = expect_method(require_method, permit_method)
    replace_argument = true
  elsif (require_method, permit_method = params_permit_require(node))
    range = offense_range(permit_method, node)
    prefer = "expect(#{permit_method.arguments.map(&:source).join(', ')})"
    replace_argument = false
  else
    return
  end

  add_offense(range, message: format(MSG, prefer: prefer)) do |corrector|
    corrector.remove(require_method.receiver.source_range.end.join(require_method.source_range.end))
    corrector.replace(permit_method.loc.selector, 'expect')
    if replace_argument
      corrector.insert_before(permit_method.first_argument, "#{require_key(require_method)}[")
      corrector.insert_after(permit_method.last_argument, ']')
    end
  end

  ignore_node(node)
end