jit_preloader 0.2.3 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/README.md +38 -1
- data/jit_preloader.gemspec +3 -2
- data/lib/jit_preloader.rb +5 -4
- data/lib/jit_preloader/active_record/associations/preloader/{association.rb → ar5_association.rb} +7 -12
- data/lib/jit_preloader/active_record/associations/preloader/ar6_association.rb +57 -0
- data/lib/jit_preloader/active_record/base.rb +60 -3
- data/lib/jit_preloader/version.rb +1 -1
- data/spec/lib/jit_preloader/active_record/base_spec.rb +94 -0
- data/spec/lib/jit_preloader/preloader_spec.rb +24 -1
- data/spec/support/models.rb +3 -0
- metadata +31 -15
- data/Gemfile.lock +0 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f6b03d3f3143dc42fbf4b980563021ed9462364d83bbb06d5c41065059c10478
|
4
|
+
data.tar.gz: 8d744ad7498e9ba3b60a01f094abd06db7a35fbbfdf594bba0cf74c9071622fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33a93b1c222276bce861ca4f441b5f4f9773f6337e39762422defe3fd3a7dedd360626512bb4869cf9b6b1c216035b93caca857093561a7c0378164e8e404085
|
7
|
+
data.tar.gz: c5c34143399f102bf1b20e8f6614cb077debad960b435d42733fbcfd8657a4be7fbec34a8e6883f614e68c1f5a19673d86ce1526f29c124463397fe8fc38aaa6
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -173,6 +173,43 @@ end
|
|
173
173
|
|
174
174
|
```
|
175
175
|
|
176
|
+
### Preloading a subset of an association
|
177
|
+
|
178
|
+
There are often times when you want to preload a subset of an association, or change how the SQL statement is generated. For example, if a `Contact` model has
|
179
|
+
an `addresses` association, you may want to be able to get all of the addresses that belong to a specific country without introducing an N+1 query.
|
180
|
+
This is a method `preload_scoped_relation` that is available that can handle this for you.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
#old
|
184
|
+
class Contact < ActiveRecord::Base
|
185
|
+
has_many :addresses
|
186
|
+
has_many :usa_addresses, ->{ where(country: Country.find_by_name("USA")) }
|
187
|
+
end
|
188
|
+
|
189
|
+
Contact.jit_preload.all.each do |contact|
|
190
|
+
# This will preload the association as expected, but it must be defined as an association in advance
|
191
|
+
contact.usa_addresses
|
192
|
+
|
193
|
+
# This will preload as the entire addresses association, and filters it in memory
|
194
|
+
contact.addresses.select{|address| address.country == Country.find_by_name("USA") }
|
195
|
+
|
196
|
+
# This is an N+1 query
|
197
|
+
contact.addresses.where(country: Country.find_by_name("USA"))
|
198
|
+
end
|
199
|
+
|
200
|
+
# New
|
201
|
+
Contact.jit_preload.all.each do |contact|
|
202
|
+
contact.preload_scoped_relation(
|
203
|
+
name: "USA Addresses",
|
204
|
+
base_association: :addresses,
|
205
|
+
preload_scope: Address.where(country: Country.find_by_name("USA"))
|
206
|
+
)
|
207
|
+
end
|
208
|
+
# SELECT * FROM contacts
|
209
|
+
# SELECT * FROM countries WHERE name = "USA" LIMIT 1
|
210
|
+
# SELECT "addresses".* FROM "addresses" WHERE "addresses"."country_id" = 10 AND "addresses"."contact_id" IN (1, 2, 3, ...)
|
211
|
+
```
|
212
|
+
|
176
213
|
### Jit preloading globally across your application
|
177
214
|
|
178
215
|
The JitPreloader can be globally enabled, in which case most N+1 queries in your app should just disappear. It is off by default.
|
@@ -201,7 +238,7 @@ This is mostly a magic bullet, but it doesn't solve all database-related problem
|
|
201
238
|
```ruby
|
202
239
|
Contact.all.each do |contact|
|
203
240
|
contact.emails.reload # Reloading the association
|
204
|
-
contact.addresses.where(billing: true).to_a # Querying the association
|
241
|
+
contact.addresses.where(billing: true).to_a # Querying the association (Use: preload_scoped_relation to avoid these)
|
205
242
|
end
|
206
243
|
```
|
207
244
|
|
data/jit_preloader.gemspec
CHANGED
@@ -18,13 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activerecord", ">
|
21
|
+
spec.add_dependency "activerecord", "> 5.0", "< 7"
|
22
22
|
spec.add_dependency "activesupport"
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler"
|
25
|
-
spec.add_development_dependency "rake", "~>
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
26
26
|
spec.add_development_dependency "rspec"
|
27
27
|
spec.add_development_dependency "database_cleaner"
|
28
28
|
spec.add_development_dependency "sqlite3"
|
29
29
|
spec.add_development_dependency "byebug"
|
30
|
+
spec.add_development_dependency "db-query-matchers"
|
30
31
|
end
|
data/lib/jit_preloader.rb
CHANGED
@@ -8,16 +8,17 @@ require 'jit_preloader/active_record/base'
|
|
8
8
|
require 'jit_preloader/active_record/relation'
|
9
9
|
require 'jit_preloader/active_record/associations/collection_association'
|
10
10
|
require 'jit_preloader/active_record/associations/singular_association'
|
11
|
-
if Gem::Version.new(ActiveRecord::VERSION::STRING)
|
11
|
+
if Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new("6.0.0")
|
12
|
+
require 'jit_preloader/active_record/associations/preloader/ar6_association'
|
13
|
+
elsif Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new("5.2.2")
|
14
|
+
require 'jit_preloader/active_record/associations/preloader/ar5_association'
|
15
|
+
else
|
12
16
|
require 'jit_preloader/active_record/associations/preloader/collection_association'
|
13
17
|
require 'jit_preloader/active_record/associations/preloader/singular_association'
|
14
|
-
else
|
15
|
-
require 'jit_preloader/active_record/associations/preloader/association'
|
16
18
|
end
|
17
19
|
require 'jit_preloader/preloader'
|
18
20
|
|
19
21
|
module JitPreloader
|
20
|
-
|
21
22
|
def self.globally_enabled=(value)
|
22
23
|
@enabled = value
|
23
24
|
end
|
data/lib/jit_preloader/active_record/associations/preloader/{association.rb → ar5_association.rb}
RENAMED
@@ -18,20 +18,13 @@ module JitPreloader
|
|
18
18
|
# end
|
19
19
|
|
20
20
|
def run(preloader)
|
21
|
-
|
22
|
-
records = load_records do |record|
|
23
|
-
owner = owners_by_key[convert_key(record[association_key_name])]
|
24
|
-
association = owner.association(reflection.name)
|
25
|
-
association.set_inverse_instance(record)
|
26
|
-
end
|
21
|
+
return unless (reflection.scope.nil? || reflection.scope.arity == 0) && klass.ancestors.include?(ActiveRecord::Base)
|
27
22
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
super.tap do
|
24
|
+
if preloaded_records.any? && preloaded_records.none?(&:jit_preloader)
|
25
|
+
JitPreloader::Preloader.attach(preloaded_records) if owners.any?(&:jit_preloader) || JitPreloader.globally_enabled?
|
26
|
+
end
|
32
27
|
end
|
33
|
-
|
34
|
-
JitPreloader::Preloader.attach(all_records) if all_records.any?
|
35
28
|
end
|
36
29
|
|
37
30
|
# Original method:
|
@@ -54,6 +47,7 @@ module JitPreloader
|
|
54
47
|
# the original copy so that we don't blow away in-memory changes.
|
55
48
|
new_records = association.target.any? ? records - association.target : records
|
56
49
|
association.target.concat(new_records)
|
50
|
+
association.loaded!
|
57
51
|
else
|
58
52
|
association.target ||= records.first unless records.empty?
|
59
53
|
end
|
@@ -69,3 +63,4 @@ module JitPreloader
|
|
69
63
|
end
|
70
64
|
|
71
65
|
ActiveRecord::Associations::Preloader::Association.prepend(JitPreloader::PreloaderAssociation)
|
66
|
+
ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(JitPreloader::PreloaderAssociation)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module JitPreloader
|
2
|
+
module PreloaderAssociation
|
3
|
+
|
4
|
+
# A monkey patch to ActiveRecord. The old method looked like the snippet
|
5
|
+
# below. Our changes here are that we remove records that are already
|
6
|
+
# part of the target, then attach all of the records to a new jit preloader.
|
7
|
+
#
|
8
|
+
# def run
|
9
|
+
# records = records_by_owner
|
10
|
+
|
11
|
+
# owners.each do |owner|
|
12
|
+
# associate_records_to_owner(owner, records[owner] || [])
|
13
|
+
# end if @associate
|
14
|
+
|
15
|
+
# self
|
16
|
+
# end
|
17
|
+
|
18
|
+
def run
|
19
|
+
return unless (reflection.scope.nil? || reflection.scope.arity == 0) && klass.ancestors.include?(ActiveRecord::Base)
|
20
|
+
|
21
|
+
super.tap do
|
22
|
+
if preloaded_records.any? && preloaded_records.none?(&:jit_preloader)
|
23
|
+
JitPreloader::Preloader.attach(preloaded_records) if owners.any?(&:jit_preloader) || JitPreloader.globally_enabled?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Original method:
|
29
|
+
# def associate_records_to_owner(owner, records)
|
30
|
+
# association = owner.association(reflection.name)
|
31
|
+
# if reflection.collection?
|
32
|
+
# association.target = records
|
33
|
+
# else
|
34
|
+
# association.target = records.first
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
def associate_records_to_owner(owner, records)
|
38
|
+
association = owner.association(reflection.name)
|
39
|
+
if reflection.collection?
|
40
|
+
new_records = association.target.any? ? records - association.target : records
|
41
|
+
association.target.concat(new_records)
|
42
|
+
association.loaded!
|
43
|
+
else
|
44
|
+
association.target = records.first
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_scope
|
49
|
+
super.tap do |scope|
|
50
|
+
scope.jit_preload! if owners.any?(&:jit_preloader) || JitPreloader.globally_enabled?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ActiveRecord::Associations::Preloader::Association.prepend(JitPreloader::PreloaderAssociation)
|
57
|
+
ActiveRecord::Associations::Preloader::ThroughAssociation.prepend(JitPreloader::PreloaderAssociation)
|
@@ -2,6 +2,7 @@ module JitPreloadExtension
|
|
2
2
|
attr_accessor :jit_preloader
|
3
3
|
attr_accessor :jit_n_plus_one_tracking
|
4
4
|
attr_accessor :jit_preload_aggregates
|
5
|
+
attr_accessor :jit_preload_scoped_relations
|
5
6
|
|
6
7
|
def reload(*args)
|
7
8
|
clear_jit_preloader!
|
@@ -10,17 +11,73 @@ module JitPreloadExtension
|
|
10
11
|
|
11
12
|
def clear_jit_preloader!
|
12
13
|
self.jit_preload_aggregates = {}
|
14
|
+
self.jit_preload_scoped_relations = {}
|
13
15
|
if jit_preloader
|
14
16
|
jit_preloader.records.delete(self)
|
15
17
|
self.jit_preloader = nil
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
if Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new("6.0.0")
|
22
|
+
def preload_scoped_relation(name:, base_association:, preload_scope: nil)
|
23
|
+
return jit_preload_scoped_relations[name] if jit_preload_scoped_relations&.key?(name)
|
24
|
+
|
25
|
+
records = jit_preloader&.records || [self]
|
26
|
+
|
27
|
+
preloader_association = ActiveRecord::Associations::Preloader.new.preload(
|
28
|
+
records,
|
29
|
+
base_association,
|
30
|
+
preload_scope
|
31
|
+
).first
|
32
|
+
|
33
|
+
records.each do |record|
|
34
|
+
record.jit_preload_scoped_relations ||= {}
|
35
|
+
association = record.association(base_association)
|
36
|
+
record.jit_preload_scoped_relations[name] = preloader_association.records_by_owner[record]
|
37
|
+
end
|
38
|
+
|
39
|
+
jit_preload_scoped_relations[name]
|
40
|
+
end
|
41
|
+
else
|
42
|
+
def preload_scoped_relation(name:, base_association:, preload_scope: nil)
|
43
|
+
return jit_preload_scoped_relations[name] if jit_preload_scoped_relations&.key?(name)
|
44
|
+
|
45
|
+
records = jit_preloader&.records || [self]
|
46
|
+
previous_association_values = {}
|
47
|
+
|
48
|
+
records.each do |record|
|
49
|
+
association = record.association(base_association)
|
50
|
+
if association.loaded?
|
51
|
+
previous_association_values[record] = association.target
|
52
|
+
association.reset
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
ActiveRecord::Associations::Preloader.new.preload(
|
57
|
+
records,
|
58
|
+
base_association,
|
59
|
+
preload_scope
|
60
|
+
)
|
61
|
+
|
62
|
+
records.each do |record|
|
63
|
+
record.jit_preload_scoped_relations ||= {}
|
64
|
+
association = record.association(base_association)
|
65
|
+
record.jit_preload_scoped_relations[name] = association.target
|
66
|
+
association.reset
|
67
|
+
if previous_association_values.key?(record)
|
68
|
+
association.target = previous_association_values[record]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
jit_preload_scoped_relations[name]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
19
76
|
def self.prepended(base)
|
20
77
|
class << base
|
21
78
|
delegate :jit_preload, to: :all
|
22
79
|
|
23
|
-
def has_many_aggregate(assoc, name, aggregate, field, default: 0)
|
80
|
+
def has_many_aggregate(assoc, name, aggregate, field, table_alias_name: nil, default: 0)
|
24
81
|
method_name = "#{assoc}_#{name}"
|
25
82
|
|
26
83
|
define_method(method_name) do |conditions={}|
|
@@ -42,8 +99,8 @@ module JitPreloadExtension
|
|
42
99
|
association_scope = association_scope.instance_exec(&reflection.scope).reorder(nil) if reflection.scope
|
43
100
|
|
44
101
|
# If the query uses an alias for the association, use that instead of the table name
|
45
|
-
|
46
|
-
table_reference
|
102
|
+
table_reference = table_alias_name
|
103
|
+
table_reference ||= association_scope.references_values.first || aggregate_association.table_name
|
47
104
|
|
48
105
|
conditions[table_reference] = { aggregate_association.foreign_key => primary_ids }
|
49
106
|
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "db-query-matchers"
|
3
|
+
|
4
|
+
RSpec.describe "ActiveRecord::Base Extensions" do
|
5
|
+
|
6
|
+
let(:canada) { Country.create(name: "Canada") }
|
7
|
+
let(:usa) { Country.create(name: "U.S.A") }
|
8
|
+
|
9
|
+
describe "#preload_scoped_relation" do
|
10
|
+
def call(contact)
|
11
|
+
contact.preload_scoped_relation(
|
12
|
+
name: "American Addresses",
|
13
|
+
base_association: :addresses,
|
14
|
+
preload_scope: Address.where(country: usa)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
Contact.create(name: "Bar", addresses: [
|
20
|
+
Address.new(street: "123 Fake st", country: canada),
|
21
|
+
Address.new(street: "21 Jump st", country: usa),
|
22
|
+
Address.new(street: "90210 Beverly Hills", country: usa)
|
23
|
+
])
|
24
|
+
|
25
|
+
Contact.create(name: "Foo", addresses: [
|
26
|
+
Address.new(street: "1 First st", country: canada),
|
27
|
+
Address.new(street: "10 Tenth Ave", country: usa)
|
28
|
+
])
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when operating on a single object" do
|
32
|
+
it "will load the objects for that object" do
|
33
|
+
contact = Contact.first
|
34
|
+
expect(call(contact)).to match_array contact.addresses.where(country: usa).to_a
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "memoizes the result" do
|
39
|
+
contacts = Contact.jit_preload.limit(2).to_a
|
40
|
+
|
41
|
+
expect do
|
42
|
+
expect(call(contacts.first))
|
43
|
+
expect(call(contacts.first))
|
44
|
+
end.to make_database_queries(count: 1)
|
45
|
+
end
|
46
|
+
|
47
|
+
context "when reloading the object" do
|
48
|
+
it "clears the memoization" do
|
49
|
+
contacts = Contact.jit_preload.limit(2).to_a
|
50
|
+
|
51
|
+
expect do
|
52
|
+
expect(call(contacts.first))
|
53
|
+
end.to make_database_queries(count: 1)
|
54
|
+
contacts.first.reload
|
55
|
+
expect do
|
56
|
+
expect(call(contacts.first))
|
57
|
+
end.to make_database_queries(count: 1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "will issue one query for the group of objects" do
|
62
|
+
contacts = Contact.jit_preload.limit(2).to_a
|
63
|
+
|
64
|
+
usa_addresses = contacts.first.addresses.where(country: usa).to_a
|
65
|
+
expect do
|
66
|
+
expect(call(contacts.first)).to match_array usa_addresses
|
67
|
+
end.to make_database_queries(count: 1)
|
68
|
+
|
69
|
+
usa_addresses = contacts.last.addresses.where(country: usa).to_a
|
70
|
+
expect do
|
71
|
+
expect(call(contacts.last)).to match_array usa_addresses
|
72
|
+
end.to_not make_database_queries
|
73
|
+
end
|
74
|
+
|
75
|
+
it "doesn't load the value into the association" do
|
76
|
+
contacts = Contact.jit_preload.limit(2).to_a
|
77
|
+
call(contacts.first)
|
78
|
+
|
79
|
+
expect(contacts.first.association(:addresses)).to_not be_loaded
|
80
|
+
expect(contacts.last.association(:addresses)).to_not be_loaded
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when the association is already loaded" do
|
84
|
+
it "doesn't change the value of the association" do
|
85
|
+
contacts = Contact.jit_preload.limit(2).to_a
|
86
|
+
contacts.each{|contact| contact.addresses.to_a }
|
87
|
+
contacts.each{|contact| call(contact) }
|
88
|
+
|
89
|
+
expect(contacts.first.association(:addresses)).to be_loaded
|
90
|
+
expect(contacts.last.association(:addresses)).to be_loaded
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
RSpec.describe JitPreloader::Preloader do
|
4
4
|
let!(:contact1) do
|
@@ -106,6 +106,19 @@ RSpec.describe JitPreloader::Preloader do
|
|
106
106
|
expect(contact_books.first.children).to include(child1, child2, child3)
|
107
107
|
end
|
108
108
|
end
|
109
|
+
|
110
|
+
context "when preloading an aggregate for a child model scoped by another join table" do
|
111
|
+
let!(:contact_book) { ContactBook.create(name: "The Yellow Pages") }
|
112
|
+
let!(:contact1) { Company.create(name: "Without Email", contact_book: contact_book) }
|
113
|
+
let!(:contact2) { Company.create(name: "With Blank Email", email_address: EmailAddress.new(address: ""), contact_book: contact_book) }
|
114
|
+
let!(:contact3) { Company.create(name: "With Email", email_address: EmailAddress.new(address: "a@a.com"), contact_book: contact_book) }
|
115
|
+
|
116
|
+
it "can handle queries" do
|
117
|
+
contact_books = ContactBook.jit_preload.to_a
|
118
|
+
expect(contact_books.first.companies_with_blank_email_address_count).to eq 1
|
119
|
+
expect(contact_books.first.companies_with_blank_email_address).to eq [contact2]
|
120
|
+
end
|
121
|
+
end
|
109
122
|
end
|
110
123
|
|
111
124
|
context "when preloading an aggregate as polymorphic" do
|
@@ -141,6 +154,16 @@ RSpec.describe JitPreloader::Preloader do
|
|
141
154
|
expect(c.contacts_count).to eql contact_owner_counts[i]
|
142
155
|
end
|
143
156
|
end
|
157
|
+
|
158
|
+
context "when a record has a polymorphic association type that's not an ActiveRecord" do
|
159
|
+
before do
|
160
|
+
contact1.update!(contact_owner_type: "NilClass", contact_owner_id: nil)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "doesn't die while trying to load the association" do
|
164
|
+
expect(Contact.jit_preload.map(&:contact_owner)).to eq [nil, ContactOwner.first, Address.first]
|
165
|
+
end
|
166
|
+
end
|
144
167
|
end
|
145
168
|
end
|
146
169
|
|
data/spec/support/models.rb
CHANGED
@@ -12,6 +12,9 @@ class ContactBook < ActiveRecord::Base
|
|
12
12
|
has_many_aggregate :employees, :count, :count, "*"
|
13
13
|
has_many_aggregate :company_employees, :count, :count, "*"
|
14
14
|
has_many_aggregate :children, :count, :count, "*"
|
15
|
+
|
16
|
+
has_many :companies_with_blank_email_address, -> { joins(:email_address).where(email_addresses: { address: "" }) }, class_name: "Company"
|
17
|
+
has_many_aggregate :companies_with_blank_email_address, :count, :count, "*", table_alias_name: "contacts"
|
15
18
|
end
|
16
19
|
|
17
20
|
class Contact < ActiveRecord::Base
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jit_preloader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle d'Oliveira
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - ">"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '5.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '13.0'
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '13.0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: rspec
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,6 +128,20 @@ dependencies:
|
|
128
128
|
- - ">="
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: db-query-matchers
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
131
145
|
description: The JitPreloader has the ability to send notifications when N+1 queries
|
132
146
|
occur to help guage how problematic they are for your code base and a way to remove
|
133
147
|
all of the commons explicitly or automatically
|
@@ -140,14 +154,14 @@ files:
|
|
140
154
|
- ".gitignore"
|
141
155
|
- ".rspec"
|
142
156
|
- Gemfile
|
143
|
-
- Gemfile.lock
|
144
157
|
- LICENSE
|
145
158
|
- README.md
|
146
159
|
- Rakefile
|
147
160
|
- jit_preloader.gemspec
|
148
161
|
- lib/jit_preloader.rb
|
149
162
|
- lib/jit_preloader/active_record/associations/collection_association.rb
|
150
|
-
- lib/jit_preloader/active_record/associations/preloader/
|
163
|
+
- lib/jit_preloader/active_record/associations/preloader/ar5_association.rb
|
164
|
+
- lib/jit_preloader/active_record/associations/preloader/ar6_association.rb
|
151
165
|
- lib/jit_preloader/active_record/associations/preloader/collection_association.rb
|
152
166
|
- lib/jit_preloader/active_record/associations/preloader/singular_association.rb
|
153
167
|
- lib/jit_preloader/active_record/associations/singular_association.rb
|
@@ -155,6 +169,7 @@ files:
|
|
155
169
|
- lib/jit_preloader/active_record/relation.rb
|
156
170
|
- lib/jit_preloader/preloader.rb
|
157
171
|
- lib/jit_preloader/version.rb
|
172
|
+
- spec/lib/jit_preloader/active_record/base_spec.rb
|
158
173
|
- spec/lib/jit_preloader/preloader_spec.rb
|
159
174
|
- spec/spec_helper.rb
|
160
175
|
- spec/support/database.rb
|
@@ -163,7 +178,7 @@ homepage: ''
|
|
163
178
|
licenses:
|
164
179
|
- MIT
|
165
180
|
metadata: {}
|
166
|
-
post_install_message:
|
181
|
+
post_install_message:
|
167
182
|
rdoc_options: []
|
168
183
|
require_paths:
|
169
184
|
- lib
|
@@ -178,12 +193,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
193
|
- !ruby/object:Gem::Version
|
179
194
|
version: '0'
|
180
195
|
requirements: []
|
181
|
-
rubyforge_project:
|
182
|
-
rubygems_version: 2.
|
183
|
-
signing_key:
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 2.7.6.2
|
198
|
+
signing_key:
|
184
199
|
specification_version: 4
|
185
200
|
summary: Tool to understand N+1 queries and to remove them
|
186
201
|
test_files:
|
202
|
+
- spec/lib/jit_preloader/active_record/base_spec.rb
|
187
203
|
- spec/lib/jit_preloader/preloader_spec.rb
|
188
204
|
- spec/spec_helper.rb
|
189
205
|
- spec/support/database.rb
|
data/Gemfile.lock
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
jit_preloader (0.2.1)
|
5
|
-
activerecord (> 4.2, < 6)
|
6
|
-
activesupport
|
7
|
-
|
8
|
-
GEM
|
9
|
-
remote: https://rubygems.org/
|
10
|
-
specs:
|
11
|
-
activemodel (5.2.2)
|
12
|
-
activesupport (= 5.2.2)
|
13
|
-
activerecord (5.2.2)
|
14
|
-
activemodel (= 5.2.2)
|
15
|
-
activesupport (= 5.2.2)
|
16
|
-
arel (>= 9.0)
|
17
|
-
activesupport (5.2.2)
|
18
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
19
|
-
i18n (>= 0.7, < 2)
|
20
|
-
minitest (~> 5.1)
|
21
|
-
tzinfo (~> 1.1)
|
22
|
-
arel (9.0.0)
|
23
|
-
byebug (9.0.6)
|
24
|
-
concurrent-ruby (1.1.4)
|
25
|
-
database_cleaner (1.5.3)
|
26
|
-
diff-lcs (1.2.5)
|
27
|
-
i18n (1.6.0)
|
28
|
-
concurrent-ruby (~> 1.0)
|
29
|
-
minitest (5.11.3)
|
30
|
-
rake (10.5.0)
|
31
|
-
rspec (3.5.0)
|
32
|
-
rspec-core (~> 3.5.0)
|
33
|
-
rspec-expectations (~> 3.5.0)
|
34
|
-
rspec-mocks (~> 3.5.0)
|
35
|
-
rspec-core (3.5.4)
|
36
|
-
rspec-support (~> 3.5.0)
|
37
|
-
rspec-expectations (3.5.0)
|
38
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
-
rspec-support (~> 3.5.0)
|
40
|
-
rspec-mocks (3.5.0)
|
41
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
-
rspec-support (~> 3.5.0)
|
43
|
-
rspec-support (3.5.0)
|
44
|
-
sqlite3 (1.3.12)
|
45
|
-
thread_safe (0.3.6)
|
46
|
-
tzinfo (1.2.5)
|
47
|
-
thread_safe (~> 0.1)
|
48
|
-
|
49
|
-
PLATFORMS
|
50
|
-
ruby
|
51
|
-
|
52
|
-
DEPENDENCIES
|
53
|
-
bundler
|
54
|
-
byebug
|
55
|
-
database_cleaner
|
56
|
-
jit_preloader!
|
57
|
-
rake (~> 10.0)
|
58
|
-
rspec
|
59
|
-
sqlite3
|
60
|
-
|
61
|
-
BUNDLED WITH
|
62
|
-
2.0.1
|