@@ -90,16 +90,16 @@ This gem will publish an `n_plus_one_query` event via ActiveSupport::Notificatio
9090
9191You could implement some basic tracking. This will let you measure the extent of the N+1 query problems in your app:
9292``` ruby
93- ActiveSupport ::Notifications .subscribe(" n_plus_one_query" ) do |event , data |
93+ ActiveSupport ::Notifications .subscribe(' n_plus_one_query' ) do |event , data |
9494 statsd.increment " web.#{ Rails .env} .n_plus_one_queries.global"
9595end
9696```
9797
9898You could log the N+1 queries. In your development environment, you could throw N+1 queries into the logs along with a stack trace:
9999``` ruby
100- ActiveSupport ::Notifications .subscribe(" n_plus_one_query" ) do |event , data |
100+ ActiveSupport ::Notifications .subscribe(' n_plus_one_query' ) do |event , data |
101101 message = " N+1 Query detected: #{ data[:association ] } on #{ data[:source ].class } "
102- backtrace = caller .select { |r | r.starts_with?(Rails .root.to_s) }
102+ backtrace = caller .select { |r | r.starts_with?(Rails .root.to_s) }
103103 Rails .logger.debug(" \n\n #{ message } \n #{ backtrace.join(" \n " ) } \n " .red)
104104end
105105```
@@ -113,7 +113,7 @@ config.around(:each) do |example|
113113 raise QueryError .new (message)
114114 end
115115 end
116- ActiveSupport ::Notifications .subscribed(callback, " n_plus_one_query" ) do
116+ ActiveSupport ::Notifications .subscribed(callback, ' n_plus_one_query' ) do
117117 example.run
118118 end
119119end
@@ -144,7 +144,7 @@ There is now a `has_many_aggregate` method available for ActiveRecord::Base. Thi
144144``` ruby
145145# old
146146Contact .all.each do |contact |
147- contact.addresses.maximum(" LENGTH(street)" )
147+ contact.addresses.maximum(' LENGTH(street)' )
148148 contact.addresses.count
149149end
150150# SELECT * FROM contacts
159159# new
160160class Contact < ActiveRecord ::Base
161161 has_many :addresses
162- has_many_aggregate :addresses , :max_street_length , :maximum , " LENGTH(street)" , default: nil
163- has_many_aggregate :addresses , :count_all , :count , " * "
162+ has_many_aggregate :addresses , :max_street_length , :maximum , ' LENGTH(street)' , default: nil
163+ has_many_aggregate :addresses , :count_all , :count , ' * '
164164end
165165
166166Contact .jit_preload.each do |contact |
@@ -177,7 +177,7 @@ Furthermore, there is an argument `max_ids_per_query` setting max ids per query.
177177``` ruby
178178class Contact < ActiveRecord ::Base
179179 has_many :addresses
180- has_many_aggregate :addresses , :count_all , :count , " * " , max_ids_per_query: 10
180+ has_many_aggregate :addresses , :count_all , :count , ' * ' , max_ids_per_query: 10
181181end
182182
183183Contact .jit_preload.each do |contact |
@@ -197,26 +197,26 @@ This is a method `preload_scoped_relation` that is available that can handle thi
197197# old
198198class Contact < ActiveRecord ::Base
199199 has_many :addresses
200- has_many :usa_addresses , -> { where(country: Country .find_by_name(" USA" )) }
200+ has_many :usa_addresses , -> { where(country: Country .find_by_name(' USA' )) }
201201end
202202
203203Contact .jit_preload.all.each do |contact |
204204 # This will preload the association as expected, but it must be defined as an association in advance
205205 contact.usa_addresses
206206
207207 # This will preload as the entire addresses association, and filters it in memory
208- contact.addresses.select { |address | address.country == Country .find_by_name(" USA" ) }
208+ contact.addresses.select { |address | address.country == Country .find_by_name(' USA' ) }
209209
210210 # This is an N+1 query
211- contact.addresses.where(country: Country .find_by_name(" USA" ))
211+ contact.addresses.where(country: Country .find_by_name(' USA' ))
212212end
213213
214214# New
215215Contact .jit_preload.all.each do |contact |
216216 contact.preload_scoped_relation(
217- name: " USA Addresses" ,
217+ name: ' USA Addresses' ,
218218 base_association: :addresses ,
219- preload_scope: Address .where(country: Country .find_by_name(" USA" ))
219+ preload_scope: Address .where(country: Country .find_by_name(' USA' ))
220220 )
221221end
222222# SELECT * FROM contacts
@@ -236,14 +236,14 @@ JitPreloader.globally_enabled = true
236236# Can also be given anything that responds to `call`.
237237# You could build a kill switch with Redis (or whatever you'd like)
238238# so that you can turn it on or off dynamically.
239- JitPreloader .globally_enabled = -> { $redis .get(' always_jit_preload' ) == ' on' }
239+ JitPreloader .globally_enabled = -> { $redis .get(' always_jit_preload' ) == ' on' }
240240
241241# Setting global max ids constraint on all aggregation methods.
242242JitPreloader .max_ids_per_query = 10
243243
244244class Contact < ActiveRecord ::Base
245245 has_many :emails
246- has_many_aggregate :emails , :count_all , :count , " * "
246+ has_many_aggregate :emails , :count_all , :count , ' * '
247247end
248248
249249# When enabled globally, this would not generate an N+1 query.
0 commit comments