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

[Fix #1016] Add Rails/RedundantActiveRecordAllMethod cop #1020

Merged
merged 1 commit into from
Aug 28, 2023

Conversation

masato-bkn
Copy link
Contributor

@masato-bkn masato-bkn commented Jun 17, 2023

Fix: #1016

I'd like to add Rails/RedundantAll cop.
This cop detects redundant all used as a receiver for Active Record query method except user defined scope.


Before submitting the PR make sure the following are checked:

  • The PR relates to only one subject with a clear title and description in grammatically correct, complete sentences.
  • Wrote good commit messages.
  • Commit message starts with [Fix #issue-number] (if the related issue exists).
  • Feature branch is up-to-date with master (if not - rebase it).
  • Squashed related commits together.
  • Added tests.
  • Ran bundle exec rake default. It executes all tests and runs RuboCop on its own code.
  • Added an entry (file) to the changelog folder named {change_type}_{change_description}.md if the new code introduces user-observable changes. See changelog entry format for details.
  • If this is a new cop, consider making a corresponding update to the Rails Style Guide.

@masato-bkn masato-bkn changed the title [Fix: #1016] Add Rails/RedundantAll cop [Fix #1016] Add Rails/RedundantAll cop Jun 17, 2023
@koic
Copy link
Member

koic commented Jul 19, 2023

@masato-bkn ping.

@masato-bkn
Copy link
Contributor Author

@koic

If this is a new cop, consider making a corresponding update to the Rails Style Guide.

Sorry, I realized I should have made the suggestion to the Rails Style Guide first. I will contact you again once I have worked on it.

@masato-bkn
Copy link
Contributor Author

masato-bkn commented Jul 19, 2023

rubocop/rails-style-guide#339
I have created an issue about redundant all in the Rails Style Guide.

@masato-bkn masato-bkn force-pushed the add_rails_redundant_all branch 3 times, most recently from 4aa8ede to e6a3ff5 Compare August 11, 2023 09:54
# # good
# User.order(:created_at)
# User.find(id)
class RedundantAll < Base
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RedundantAll might be too abstract. How about RedundantActiveRecordAllMethod?

Suggested change
class RedundantAll < Base
class RedundantActiveRecordAllMethod < Base

include ActiveRecordHelper
extend AutoCorrector

MSG = 'Redundant `all` detected'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The period is forgotten.

Suggested change
MSG = 'Redundant `all` detected'
MSG = 'Redundant `all` detected.'

return unless QUERYING_METHODS.include?(query_node.method_name)
return if node.receiver.nil? && !inherit_active_record_base?(node)

all_range = node.loc.selector
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
all_range = node.loc.selector
range_of_all_method = node.loc.selector

'without(user)'
]

describe '::QUERYING_METHODS' do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
describe '::QUERYING_METHODS' do
describe "#{described_class}::QUERYING_METHODS" do

Comment on lines 4 to 99
sources = [
'and(User.where(age: 30))',
'annotate("selecting id")',
'any?',
'average(:age)',
'calculate(:average, :age)',
'count',
'create_or_find_by(name: name)',
'create_or_find_by!(name: name)',
'create_with(name: name)',
'delete_all',
'delete_by(id: id)',
'destroy_all',
'destroy_by(id: id)',
'distinct',
'eager_load(:posts)',
'except(:order)',
'excluding(user)',
'exists?',
'extending(Pagination)',
'extract_associated(:posts)',
'fifth',
'fifth!',
'find(id)',
'find_by(name: name)',
'find_by!(name: name)',
'find_each(&:do_something)',
'find_in_batches(&:do_something)',
'find_or_create_by(name: name)',
'find_or_create_by!(name: name)',
'find_or_initialize_by(name: name)',
'find_sole_by(name: name)',
'first',
'first!',
'first_or_create(name: name)',
'first_or_create!(name: name)',
'first_or_initialize(name: name)',
'forty_two',
'forty_two!',
'fourth',
'fourth!',
'from("users")',
'group(:age)',
'having("AVG(age) > 30")',
'ids',
'in_batches(&:do_something)',
'in_order_of(:id, ids)',
'includes(:posts)',
'invert_where',
'joins(:posts)',
'last',
'last!',
'left_joins(:posts)',
'left_outer_joins(:posts)',
'limit(n)',
'lock',
'many?',
'maximum(:age)',
'merge(users)',
'minimum(:age)',
'none',
'none?',
'offset(n)',
'one?',
'only(:order)',
'optimizer_hints("SeqScan(users)", "Parallel(users 8)")',
'or(User.where(age: 30))',
'order(:created_at)',
'pick(:id)',
'pluck(:age)',
'preload(:posts)',
'readonly',
'references(:posts)',
'reorder(:created_at)',
'reselect(:age)',
'rewhere(id: ids)',
'second',
'second!',
'second_to_last',
'second_to_last!',
'select(:age)',
'sole',
'strict_loading',
'sum(:age)',
'take(n)',
'take!',
'third',
'third!',
'third_to_last',
'third_to_last!',
'touch_all',
'unscope(:order)',
'update_all(name: name)',
'where(id: ids)',
'without(user)'
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use let instead of local variable assignment?

Comment on lines 102 to 105
it 'contains all of the querying methods' do
methods = sources.map { |s| s.split('(')[0].to_sym }
expect(described_class::QUERYING_METHODS).to eq(methods)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it 'contains all of the querying methods' do
methods = sources.map { |s| s.split('(')[0].to_sym }
expect(described_class::QUERYING_METHODS).to eq(methods)
end
let(:querying_methods) { sources.map { |s| s.split('(')[0].to_sym } }
it 'contains all of the querying methods' do
expect(described_class::QUERYING_METHODS).to eq(querying_methods)
end

RUBY
end

it 'does not register an offense when not using defined methods in ::QUERYING_METHODS' do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

::QUERYING_METHODS seems like cbase. Can you update ActiveRecord::Querying::QUERYING_METHODS or RuboCop::Cop::Rails::RedundantAll::QUERYING_METHODS (you intend) ?

@masato-bkn
Copy link
Contributor Author

@koic
Thank you for your review. I'll make the necessary changes.

@masato-bkn
Copy link
Contributor Author

@koic
I've made several changes, including addressing the points you raised.
If it looks good, I'll squash the commits into one.

@@ -775,6 +775,12 @@ Rails/ReadWriteAttribute:
Include:
- app/models/**/*.rb

Rails/RedundantActiveRecordAllMethod:
Description: Detect redundant `all` used as a receiver for Active Record query methods.
Enabled: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Enabled: true
Enabled: pending

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've addressed it.

return unless QUERYING_METHODS.include?(query_node.method_name)
return if node.receiver.nil? && !inherit_active_record_base?(node)

range_of_all_method = node.loc.selector
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should also be able to handle the following cases:
rubocop/rails-style-guide#340 (comment)

Copy link
Contributor Author

@masato-bkn masato-bkn Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've already addressed cases where an Active Record query method follows all, as shown below:

# bad
current_user.likes.all.order(:created_at)

# good
current_user.likes.order(:created_at)

https://github.com/rubocop/rubocop-rails/pull/1020/files#diff-8d2292cab6c23118ba7721e07148d49a27043e9202c75084bd49b25053a1575eR216

Should I also consider addressing cases where the receiver is a relation and no method follows all? Like this:

# bad
current_user.likes.all

# good
current_user.likes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, this is my mistake. No problem!

@masato-bkn masato-bkn changed the title [Fix #1016] Add Rails/RedundantAll cop [Fix #1016] Add Rails/RedundantActiveRecordAllMethod cop Aug 25, 2023
@@ -775,6 +775,12 @@ Rails/ReadWriteAttribute:
Include:
- app/models/**/*.rb

Rails/RedundantActiveRecordAllMethod:
Description: Detect redundant `all` used as a receiver for Active Record query methods.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rubocop/rails-style-guide#340 has been merged. Can you add the Style Guide URL and squash your commits into one?

Suggested change
Description: Detect redundant `all` used as a receiver for Active Record query methods.
Description: Detect redundant `all` used as a receiver for Active Record query methods.
StyleGuide: 'https://rails.rubystyle.guide/#redundant-all'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've addressed it and squashed the commits!

@masato-bkn masato-bkn force-pushed the add_rails_redundant_all branch 2 times, most recently from 519290c to adec01a Compare August 27, 2023 02:35
@koic koic merged commit acafbcb into rubocop:master Aug 28, 2023
10 checks passed
@koic
Copy link
Member

koic commented Aug 28, 2023

Thanks!

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 this pull request may close these issues.

New Cop idea: detect redundant all
2 participants