Class: RuboCop::Cop::OpenProject::NoParamsInWorkPackageWhereId

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

Overview

Flags ‘WorkPackage.where(id: params)` patterns. With semantic work package identifiers enabled, params may carry strings like “PROJ-42” that PostgreSQL silently casts to integer 0 inside `where(id: …)`, producing an empty result set instead of an error. Use the dedicated resolver `WorkPackage.where_display_id_in(…)` which partitions numeric and semantic inputs and consults the alias table.

The cop fires when the receiver chain demonstrably resolves to a WorkPackage relation — either rooted at the ‘WorkPackage` constant or passing through an association call whose name ends in `work_packages` (e.g. `project.work_packages`, `user.assigned_work_packages`) — and the value is derived from `params`. Internal subquery composition (`where(id: scope.pluck(:id))`) and primary-key literals are left alone.

Examples:

# bad
WorkPackage.where(id: params[:work_package_id])

# bad
WorkPackage.where(id: params[:work_package_id] || params[:ids])

# bad
WorkPackage.includes(:project).where(id: params[:ids])

# bad
project.work_packages.where(id: params[:work_package_id])

# bad
current_user.assigned_work_packages.where(id: params[:ids])

# good
WorkPackage.where_display_id_in(params[:work_package_id])

# good
project.work_packages.where_display_id_in(params[:work_package_id])

# good (primary key, not user input)
WorkPackage.where(id: 42)

# good (subquery, not user input)
WorkPackage.where(id: other_scope.select(:id))

Constant Summary collapse

MSG =
"Avoid `WorkPackage.where(id: params[...])` — semantic identifiers like " \
'"PROJ-42" are silently coerced to 0 by the SQL cast. ' \
"Use `WorkPackage.where_display_id_in(...)` instead."
RESTRICT_ON_SEND =
%i[where].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rubocop/cop/open_project/no_params_in_work_package_where_id.rb', line 75

def on_send(node)
  return unless work_package_relation?(node.receiver)

  hash_arg = node.first_argument
  id_value = id_value_from_hash(hash_arg)
  return unless id_value && value_uses_params?(id_value)

  add_offense(node) do |corrector|
    next unless autocorrectable_value?(id_value) && sole_id_predicate?(hash_arg)

    corrector.replace(node, "#{node.receiver.source}.where_display_id_in(#{id_value.source})")
  end
end