This PR modifies the Rails/Pluck cop to ignore map/collect when used inside blocks to prevent potential N+1 queries.
When the receiver's relation is not loaded and pluck is used inside an iteration, it can result in N+1 queries. This happens because pluck executes a database query on every iteration when the relation is not loaded.
Example
users = User.all
5.times do
users.map { |user| user[:id] } # Only one query is executed
end
users = User.all
5.times do
users.pluck(:id) # A query is executed on every iteration
end
users = User.all
users.load
5.times do
users.pluck(:id) # Since the records are loaded, only one query is executed
end
As shown above, replacing map/collect with pluck in such cases can degrade performance due to the N+1 queries. To prevent this, it is better to ignore map/collect when used inside an iteration.
Challenge
Since Ruby has numerous methods for performing iterations, it is difficult to list all of them. Therefore, this PR assumes that map/collect used inside blocks are likely part of an iteration and ignores offenses.
Before submitting the PR make sure the following are checked:
[x] The PR relates to only one subject with a clear title and description in grammatically correct, complete sentences.
[ ] Commit message starts with [Fix #issue-number] (if the related issue exists).
[x] Feature branch is up-to-date with master (if not - rebase it).
[x] Squashed related commits together.
[x] Added tests.
[x] Ran bundle exec rake default. It executes all tests and runs RuboCop on its own code.
[x] 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.
This PR modifies the
Rails/Pluck
cop to ignoremap/collect
when used inside blocks to prevent potential N+1 queries.When the receiver's relation is not loaded and
pluck
is used inside an iteration, it can result in N+1 queries. This happens becausepluck
executes a database query on every iteration when the relation is not loaded.Example
As shown above, replacing
map/collect
withpluck
in such cases can degrade performance due to the N+1 queries. To prevent this, it is better to ignoremap/collect
when used inside an iteration.Challenge
Since Ruby has numerous methods for performing iterations, it is difficult to list all of them. Therefore, this PR assumes that
map/collect
used inside blocks are likely part of an iteration and ignores offenses.Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.