File tree Expand file tree Collapse file tree 3 files changed +63
-0
lines changed Expand file tree Collapse file tree 3 files changed +63
-0
lines changed Original file line number Diff line number Diff line change
1
+ * [ #1388 ] ( https://github.com/rubocop/rubocop-rails/pull/1388 ) : Modify ` Rails/Pluck ` to ignore ` map/collect ` when used inside blocks to prevent potential N+1 queries. ([ @masato-bkn ] [ ] )
Original file line number Diff line number Diff line change @@ -9,6 +9,24 @@ module Rails
9
9
# element in an enumerable. When called on an Active Record relation, it
10
10
# results in a more efficient query that only selects the necessary key.
11
11
#
12
+ # NOTE: If the receiver's relation is not loaded and `pluck` is used inside an iteration,
13
+ # it may result in N+1 queries because `pluck` queries the database on each iteration.
14
+ # This cop ignores offenses for `map/collect` when they are suspected to be part of an iteration
15
+ # to prevent such potential issues.
16
+ #
17
+ # [source,ruby]
18
+ # ----
19
+ # users = User.all
20
+ # 5.times do
21
+ # users.map { |user| user[:foo] } # Only one query is executed
22
+ # end
23
+ #
24
+ # users = User.all
25
+ # 5.times do
26
+ # users.pluck(:id) # A query is executed on every iteration
27
+ # end
28
+ # ----
29
+ #
12
30
# @safety
13
31
# This cop is unsafe because model can use column aliases.
14
32
#
@@ -42,6 +60,8 @@ class Pluck < Base
42
60
PATTERN
43
61
44
62
def on_block ( node )
63
+ return if node . each_ancestor ( :block , :numblock ) . any?
64
+
45
65
pluck_candidate? ( node ) do |argument , key |
46
66
next if key . regexp_type? || !use_one_block_argument? ( argument )
47
67
Original file line number Diff line number Diff line change 128
128
end
129
129
end
130
130
end
131
+
132
+ context "when `#{ method } ` is used in block" do
133
+ it 'does not register an offense' do
134
+ expect_no_offenses ( <<~RUBY )
135
+ n.each do |x|
136
+ x.#{ method } { |a| a[:foo] }
137
+ end
138
+ RUBY
139
+ end
140
+ end
141
+
142
+ context "when `#{ method } ` is used in block with other operations" do
143
+ it 'does not register an offense' do
144
+ expect_no_offenses ( <<~RUBY )
145
+ n.each do |x|
146
+ do_something
147
+ x.#{ method } { |a| a[:foo] }
148
+ end
149
+ RUBY
150
+ end
151
+ end
152
+
153
+ context "when `#{ method } ` is used in numblock" do
154
+ it 'does not register an offense' do
155
+ expect_no_offenses ( <<~RUBY )
156
+ n.each do
157
+ _1.#{ method } { |a| a[:foo] }
158
+ end
159
+ RUBY
160
+ end
161
+ end
162
+
163
+ context "when `#{ method } ` is used in numblock with other operations" do
164
+ it 'does not register an offense' do
165
+ expect_no_offenses ( <<~RUBY )
166
+ n.each do
167
+ do_something
168
+ _1.#{ method } { |a| a[:foo] }
169
+ end
170
+ RUBY
171
+ end
172
+ end
131
173
end
132
174
133
175
context 'when using Rails 4.2 or older' , :rails42 do
You can’t perform that action at this time.
0 commit comments