Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rails/PluckId is not excluding array collections #301

Closed
beetlegius-jt opened this issue Jul 21, 2020 · 11 comments · Fixed by #307
Closed

Rails/PluckId is not excluding array collections #301

beetlegius-jt opened this issue Jul 21, 2020 · 11 comments · Fixed by #307

Comments

@beetlegius-jt
Copy link

Expected behavior

No alerts for arrays.

Actual behavior

Rails/PluckId raises an alert when using pluck(:id) with array collections.
Arrays does not support .ids, that only works for ActiveRecord::Relation collections.

Steps to reproduce the problem

I have this code:

array = [{ id: 1 }, { id: 2 }]
extracted_ids = array.pluck(:id)

Rubocop suggestion:

Rails/PluckId: Use ids instead of pluck(:id).
    extracted_ids = array.pluck(:id)
                          ^^^^^^^^^^

Updated code:

array = [{ id: 1 }, { id: 2 }]
extracted_ids = array.ids

Then it produces the following error:

NoMethodError: undefined method `ids' for [{:id=>1}, {:id=>2}]:Array

RuboCop version

bundle exec rubocop -V
0.88.0 (using Parser 2.7.1.4, rubocop-ast 0.2.0, running on ruby 2.7.1 x86_64-linux)
@koic
Copy link
Member

koic commented Jul 21, 2020

The Rails/PluckId cop is already marked unsafe (Safe: No).
https://docs.rubocop.org/rubocop-rails/2.7/cops_rails.html#railspluckid

On the other hand, it is difficult to know a receiver type in the current static analysis implementation. So, It may be possible to consider disable the cop by default if there are many false alarms to users.

@beetlegius-jt
Copy link
Author

The Rails/PluckId cop is already marked unsafe (Safe: No).
https://docs.rubocop.org/rubocop-rails/2.7/cops_rails.html#railspluckid

On the other hand, it is difficult to know a receiver type in the current static analysis implementation. So, It may be possible to consider disable the cop by default if there are many false alarms to users.

Sure, I've disabled the cop because otherwise I have to add a lot of disable comments when using pluck with array collections.

Maybe you can check if it responds to ids as a guard clause. 🤔 not sure if it's possible in the current implementation.

@koic
Copy link
Member

koic commented Jul 22, 2020

Yeah, it would be redundant to introduce respond_to?(:ids) even when it is not needed :-)
It seems better to set Safe: false by default for this cop. Thank you for the feedback!

@beetlegius-jt
Copy link
Author

Yeah, it would be redundant to introduce respond_to?(:ids) even when it is not needed :-)
It seems better to set Safe: false by default for this cop. Thank you for the feedback!

What do you mean? I have the cop disabled because otherwise it will not pass the CI rubocop check.
I mean, it's not an rubocop --auto-correct thing. There are "false alarms" when enabling this cop.

An alternative could be to add a rubocop:disable Rails/PluckId to every line that makes a pluck to an array, but there are ~ 15 occurrences in this project, and I think the same thing happens to most people.

@koic
Copy link
Member

koic commented Jul 22, 2020

It seems better to set Safe: false by default for this cop.

Ah, I was typo. Correctly it is Enabled: false.

koic added a commit to koic/rubocop-rails that referenced this issue Jul 22, 2020
Fixes rubocop#301.

This PR sets disabled by default for `Rails/PluckId`.
An array object does not support `ids` method, that only works for
an AR object. So, this PR defaults to prevent false alarms cause by it.
@koic
Copy link
Member

koic commented Jul 22, 2020

I've opened the PR #307.

@inkstak
Copy link
Contributor

inkstak commented Jul 23, 2020

Won't the same problem occur for Rails/PluckInWhere ?

Rails/PluckInWhere: Use select instead of pluck within where query method.
  Record.where(id: something.pluck(:whatever))
                             ^^^^^

something may be an array which doesn't respond to select.

@koic
Copy link
Member

koic commented Jul 23, 2020

@inkstak Sure. There will be similar problems. On the other hand, the context is narrowed down to the condition of where. It is not yet predicted how many false positives will occur in this context. So, I would like to watch the situation as a different issue. Thank you for the feedback.

@koic koic closed this as completed in #307 Jul 23, 2020
koic added a commit that referenced this issue Jul 23, 2020
…luck_id

[Fix #301] Set disabled by default for `Rails/PluckId`
@koic
Copy link
Member

koic commented Aug 2, 2020

Won't the same problem occur for Rails/PluckInWhere ?

Just FYI, I opened the PR #317 to resolve a false positive for Rails/PluckInWhere cop.

@mos-adebayo
Copy link

mos-adebayo commented Jun 15, 2023

You can use the map method instead of pluck if the collection is an Array

array = [{ id: 1 }, { id: 2 }]
extracted_ids = array.map(&:id)

@inkstak
Copy link
Contributor

inkstak commented Jun 20, 2023

@mos-adebayo It won't because Hash doesn't responds to id method.

  • map is a Ruby method to iterate a method - in shorthand version - of each item of an enumerable
  • pluck is a Rails method to iterate a key of each item
array = [{ id: 1 }, { id: 2 }]
array.pluck(:id)  # => [1, 2]
array.map(&:id)   # => undefined method `id' for {:id=>1}:Hash (NoMethodError)

Item = Data.define(:id)
array = [Item.new(1), Item.new(2)]
array.map(&:id)   #=>  [1, 2]
array.pluck(:id)  #=> undefined method `[]' for #<data Item id=1> (NoMethodError)

mjankowski added a commit to mjankowski/standard-rails that referenced this issue May 24, 2024
This cop was originally disabled with the original rubocop import: standardrb@71e48d5#diff-da3213a24b350fa386ff3bab0d6b239112408c3fe4f986cbd9d5236f7e0b61e4R458-R463

It was subsequently enabled during a mass enable commit: standardrb@24bc50f#diff-da3213a24b350fa386ff3bab0d6b239112408c3fe4f986cbd9d5236f7e0b61e4R248-R249

As discussed on this issue, the cop is unsafe by default and frequently gets false positives: rubocop/rubocop-rails#301

It is disabled by default in most recent rubocop release, for same reasons: https://github.com/rubocop/rubocop-rails/blob/v2.25.0/config/default.yml#L746-L751

Discussion of why to disable on: standardrb#31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants