Skip to content

An error occurs in Rails/SelectMap when select receiver is implicit #1121

Closed
@elektronaut

Description

@elektronaut

The error occurs when using select/map with an implicit receiver, i.e inside a model.

class Model < ApplicationRecord
  class << self
    def labels
      select("label").map(&:label)
    end
  end
end

Expected behavior

It should have been corrected to:

def labels
  pluck(:label)
end

Actual behavior

An NoMethodError is raised.

An error occurred while Rails/SelectMap cop was inspecting [rails app]/app/models/model.rb:4:6.
undefined method `begin' for nil:NilClass
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-rails-2.21.1/lib/rubocop/cop/rails/select_map.rb:55:in `autocorrect'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-rails-2.21.1/lib/rubocop/cop/rails/select_map.rb:40:in `block in on_send'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/base.rb:377:in `correct'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/base.rb:181:in `add_offense'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-rails-2.21.1/lib/rubocop/cop/rails/select_map.rb:39:in `on_send'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:143:in `public_send'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:143:in `block (2 levels) in trigger_restricted_cops'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:171:in `with_cop_error_handling'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:142:in `block in trigger_restricted_cops'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:141:in `each'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:141:in `trigger_restricted_cops'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:70:in `on_send'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:154:in `on_def'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:71:in `on_def'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:137:in `block in on_dstr'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:137:in `each'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:137:in `on_dstr'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:71:in `on_begin'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:154:in `on_class'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:71:in `on_class'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/traversal.rb:20:in `walk'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/commissioner.rb:87:in `investigate'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/team.rb:156:in `investigate_partial'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cop/team.rb:98:in `investigate'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:345:in `block in inspect_file'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:344:in `each'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:344:in `flat_map'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:344:in `inspect_file'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:287:in `block in do_inspection_loop'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:321:in `block in iterate_until_no_changes'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:314:in `loop'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:314:in `iterate_until_no_changes'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:283:in `do_inspection_loop'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:164:in `block in file_offenses'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:189:in `file_offense_cache'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:163:in `file_offenses'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:154:in `process_file'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:135:in `block in each_inspected_file'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:134:in `each'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:134:in `reduce'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:134:in `each_inspected_file'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:120:in `inspect_files'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:73:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/command/execute_runner.rb:26:in `block in execute_runner'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/command/execute_runner.rb:52:in `with_redirect'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/command/execute_runner.rb:25:in `execute_runner'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/command/execute_runner.rb:17:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/command.rb:11:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli/environment.rb:18:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli.rb:118:in `run_command'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli.rb:125:in `execute_runners'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli.rb:51:in `block in run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli.rb:77:in `profile_if_needed'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/cli.rb:43:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/exe/rubocop:19:in `block in <top (required)>'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/benchmark.rb:311:in `realtime'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/exe/rubocop:19:in `<top (required)>'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/bin/rubocop:25:in `load'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/bin/rubocop:25:in `<top (required)>'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli/exec.rb:58:in `load'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli/exec.rb:58:in `kernel_load'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli/exec.rb:23:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli.rb:492:in `exec'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli.rb:34:in `dispatch'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/cli.rb:28:in `start'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.4.10/libexec/bundle:45:in `block in <top (required)>'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/3.2.0/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/Users/inge/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/bundler-2.4.10/libexec/bundle:33:in `<top (required)>'
/Users/inge/.rbenv/versions/3.2.2/bin/bundle:25:in `load'
/Users/inge/.rbenv/versions/3.2.2/bin/bundle:25:in `<main>'

Steps to reproduce the problem

The following test case triggers the error:

it 'registers an offense when used with an implicit target' do
  expect_offense(<<~RUBY)
    select('column_name').map(&:column_name)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `pluck(:column_name)` instead of `select` with `map`.
  RUBY

  expect_correction(<<~RUBY)
    pluck(:column_name)
  RUBY
end

RuboCop version

$ rubocop -V
1.56.3 (using Parser 3.2.2.3, rubocop-ast 1.29.0, running on ruby 3.2.2) [arm64-darwin22]
  - rubocop-rails 2.21.1
  - rubocop-rspec 2.24.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions