goldiloader 0.0.11 → 0.0.12

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.
data/spec/db/database.yml DELETED
@@ -1,3 +0,0 @@
1
- sqlite3:
2
- adapter: sqlite3
3
- database: ":memory:"
data/spec/db/schema.rb DELETED
@@ -1,175 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- ActiveRecord::Schema.define(:version => 0) do
4
-
5
- create_table(:blogs, force: true) do |t|
6
- t.string :name
7
- end
8
-
9
- create_table(:posts, force: true) do |t|
10
- t.string :title
11
- t.integer :blog_id
12
- t.integer :author_id
13
- t.string :owner_type
14
- t.integer :owner_id
15
- end
16
-
17
- create_table(:users, force: true) do |t|
18
- t.string :name
19
- end
20
-
21
- create_table(:addresses, force: true) do |t|
22
- t.string :city
23
- t.integer :user_id
24
- end
25
-
26
- create_table(:groups, force: true) do |t|
27
- t.string :name
28
- end
29
-
30
- create_table(:tags, force: true) do |t|
31
- t.string :name
32
- t.integer :parent_id
33
- t.string :owner_type
34
- t.integer :owner_id
35
- end
36
-
37
- create_table(:post_tags, force: true) do |t|
38
- t.integer :post_id
39
- t.integer :tag_id
40
- end
41
- end
42
-
43
- class Tag < ActiveRecord::Base
44
- belongs_to :parent, class_name: 'Tag'
45
- has_many :children, class_name: 'Tag', foreign_key: :parent_id
46
-
47
- belongs_to :owner, polymorphic: true
48
- has_many :post_tags
49
- has_many :posts, through: :post_tags
50
-
51
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
52
- attr_accessible :name
53
- end
54
- end
55
-
56
- class PostTag < ActiveRecord::Base
57
- belongs_to :post
58
- belongs_to :tag
59
- end
60
-
61
- class Blog < ActiveRecord::Base
62
- has_many :posts
63
- has_many :posts_without_auto_include, auto_include: false, class_name: 'Post'
64
- has_many :posts_fully_load, fully_load: true, class_name: 'Post'
65
-
66
- if ActiveRecord::VERSION::MAJOR >= 4
67
- has_many :read_only_posts, -> { readonly }, class_name: 'Post'
68
- has_many :limited_posts, -> { limit(2) }, class_name: 'Post'
69
- has_many :grouped_posts, -> { group(:blog_id) }, class_name: 'Post'
70
- has_many :offset_posts, -> { offset(2) }, class_name: 'Post'
71
- has_many :from_posts, -> { from('(select distinct blog_id from posts) as posts') }, class_name: 'Post'
72
- has_many :instance_dependent_posts, ->(instance) { Post.where(blog_id: instance.id) }, class_name: 'Post'
73
-
74
- has_many :posts_ordered_by_author, -> { joins(:author).order('users.name') }, class_name: 'Post'
75
-
76
- has_many :authors_with_join, -> { joins(:address).order('addresses.city') }, through: :posts, source: :author
77
- else
78
- has_many :read_only_posts, readonly: true, class_name: 'Post'
79
- has_many :limited_posts, limit: 2, class_name: 'Post'
80
- has_many :grouped_posts, group: :blog_id, class_name: 'Post'
81
- has_many :offset_posts, offset: 2, class_name: 'Post'
82
-
83
- has_many :posts_ordered_by_author, include: :author, order: 'users.name', class_name: 'Post'
84
- end
85
-
86
- if Goldiloader::Compatibility.association_finder_sql_enabled?
87
- has_many :finder_sql_posts, finder_sql: Proc.new { "select distinct blog_id from posts where blog_id = #{self.id}" },
88
- class_name: 'Post'
89
- end
90
-
91
- has_many :posts_overridden, class_name: 'Post'
92
- has_many :authors, through: :posts
93
- has_many :addresses, through: :authors
94
-
95
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
96
- attr_accessible :name
97
- end
98
-
99
- def posts_overridden
100
- 'boom'
101
- end
102
- end
103
-
104
- class Post < ActiveRecord::Base
105
- belongs_to :blog
106
- belongs_to :blog_without_auto_include, auto_include: false, class_name: 'Blog', foreign_key: :blog_id
107
- belongs_to :author, class_name: 'User'
108
- has_many :post_tags
109
- has_many :tags, through: :post_tags
110
-
111
- belongs_to :owner, polymorphic: true
112
-
113
- if ActiveRecord::VERSION::MAJOR >= 4
114
- has_many :unique_tags, -> { distinct }, through: :post_tags, source: :tag, class_name: 'Tag'
115
- else
116
- has_many :unique_tags, through: :post_tags, source: :tag, uniq: true, class_name: 'Tag'
117
- end
118
-
119
- if ActiveRecord::VERSION::MAJOR < 4
120
- has_and_belongs_to_many :unique_tags_has_and_belongs, join_table: :post_tags, class_name: 'Tag', uniq: true
121
- end
122
-
123
- has_and_belongs_to_many :tags_without_auto_include, join_table: :post_tags, class_name: 'Tag', auto_include: false
124
-
125
- after_destroy :after_post_destroy
126
-
127
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
128
- attr_accessible :title
129
- end
130
-
131
- def after_post_destroy
132
- # Hook for tests
133
- end
134
- end
135
-
136
- class User < ActiveRecord::Base
137
- has_many :posts, foreign_key: :author_id
138
- has_many :tags, as: :owner
139
- has_one :address
140
- has_one :address_without_auto_include, auto_include: false, class_name: 'Address'
141
-
142
- if Goldiloader::Compatibility.unscope_query_method_enabled?
143
- has_one :scoped_address_with_default_scope_remove, -> { unscope(where: :city) }, class_name: 'ScopedAddress'
144
- end
145
-
146
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
147
- attr_accessible :name
148
- end
149
- end
150
-
151
- class Address < ActiveRecord::Base
152
- belongs_to :user
153
-
154
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
155
- attr_accessible :city
156
- end
157
- end
158
-
159
- class ScopedAddress < ActiveRecord::Base
160
- self.table_name = 'addresses'
161
- default_scope { where(city: ['Philadelphia'])}
162
- belongs_to :user
163
-
164
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
165
- attr_accessible :city
166
- end
167
- end
168
-
169
- class Group < ActiveRecord::Base
170
- has_many :tags, as: :owner
171
-
172
- if Goldiloader::Compatibility.mass_assignment_security_enabled?
173
- attr_accessible :name
174
- end
175
- end
@@ -1,164 +0,0 @@
1
- require 'spec_helper'
2
- require 'ostruct'
3
-
4
- describe Goldiloader::AutoIncludeContext do
5
- describe ".register_models" do
6
- context "when included_associations is an array of symbols" do
7
- let!(:roots) do
8
- [
9
- create_mock_model(cars: cars.take(2), fruit: fruits.first),
10
- create_mock_model(cars: cars.drop(2).take(2), fruit: fruits.last)
11
- ]
12
- end
13
- let!(:cars) { create_mock_models(4) }
14
- let!(:fruits) { create_mock_models(2) }
15
-
16
- before do
17
- Goldiloader::AutoIncludeContext.register_models(roots, [:cars, :fruit])
18
- end
19
-
20
- it "sets the AutoIncludeContext for roots" do
21
- expect(roots.map(&:auto_include_context).uniq.size).to eq 1
22
- expect(roots.first.auto_include_context.models).to match_array(roots)
23
- end
24
-
25
- it "sets the AutoIncludeContext for singluar nested associations" do
26
- expect(fruits.map(&:auto_include_context).uniq.size).to eq 1
27
- expect(fruits.first.auto_include_context.models).to match_array(fruits)
28
- end
29
-
30
- it "sets the AutoIncludeContext for collection nested associations" do
31
- expect(cars.map(&:auto_include_context).uniq.size).to eq 1
32
- expect(cars.first.auto_include_context.models).to match_array(cars)
33
- end
34
- end
35
-
36
- context "when included_associations is a hash" do
37
- let!(:roots) do
38
- [
39
- create_mock_model(car: cars.first),
40
- create_mock_model(car: cars.last)
41
- ]
42
- end
43
-
44
- let!(:cars) do
45
- [
46
- create_mock_model(wheels: wheels.take(4)),
47
- create_mock_model(wheels: wheels.drop(4).take(4))
48
- ]
49
- end
50
-
51
- let!(:wheels) { create_mock_models(8) }
52
-
53
- before do
54
- Goldiloader::AutoIncludeContext.register_models(roots, car: :wheels)
55
- end
56
-
57
- it "sets the AutoIncludeContext for roots" do
58
- expect(roots.map(&:auto_include_context).uniq.size).to eq 1
59
- expect(roots.first.auto_include_context.models).to match_array(roots)
60
- end
61
-
62
- it "sets the AutoIncludeContext for child nested associations" do
63
- expect(cars.map(&:auto_include_context).uniq.size).to eq 1
64
- expect(cars.first.auto_include_context.models).to match_array(cars)
65
- end
66
-
67
- it "sets the AutoIncludeContext for grandchild nested associations" do
68
- expect(wheels.map(&:auto_include_context).uniq.size).to eq 1
69
- expect(wheels.first.auto_include_context.models).to match_array(wheels)
70
- end
71
- end
72
-
73
- context "when included_associations is an array that mixes hashes and symbols" do
74
- let!(:roots) do
75
- [
76
- create_mock_model(car: cars.first, person: people.first),
77
- create_mock_model(car: cars.last, person: people.last)
78
- ]
79
- end
80
-
81
- let!(:people) { create_mock_models(2) }
82
-
83
- let!(:cars) do
84
- [
85
- create_mock_model(wheels: wheels.take(4)),
86
- create_mock_model(wheels: wheels.drop(4).take(4))
87
- ]
88
- end
89
-
90
- let!(:wheels) { create_mock_models(8) }
91
-
92
- before do
93
- Goldiloader::AutoIncludeContext.register_models(roots, [:person, car: :wheels])
94
- end
95
-
96
- it "sets the AutoIncludeContext for roots" do
97
- expect(roots.map(&:auto_include_context).uniq.size).to eq 1
98
- expect(roots.first.auto_include_context.models).to match_array(roots)
99
- end
100
-
101
- it "sets the AutoIncludeContext for child nested associations specified with a symbol" do
102
- expect(people.map(&:auto_include_context).uniq.size).to eq 1
103
- expect(people.first.auto_include_context.models).to match_array(people)
104
- end
105
-
106
- it "sets the AutoIncludeContext for child nested associations specified with a hash" do
107
- expect(cars.map(&:auto_include_context).uniq.size).to eq 1
108
- expect(cars.first.auto_include_context.models).to match_array(cars)
109
- end
110
-
111
- it "sets the AutoIncludeContext for grandchild nested associations" do
112
- expect(wheels.map(&:auto_include_context).uniq.size).to eq 1
113
- expect(wheels.first.auto_include_context.models).to match_array(wheels)
114
- end
115
- end
116
-
117
- context "when nested associations are nil" do
118
- let!(:roots) do
119
- [
120
- create_mock_model(car: cars.first),
121
- create_mock_model(car: nil),
122
- create_mock_model(car: cars.last)
123
- ]
124
- end
125
-
126
- let!(:cars) do
127
- [
128
- create_mock_model,
129
- create_mock_model
130
- ]
131
- end
132
-
133
- before do
134
- Goldiloader::AutoIncludeContext.register_models(roots, :car)
135
- end
136
-
137
- it "sets the AutoIncludeContext for roots" do
138
- expect(roots.map(&:auto_include_context).uniq.size).to eq 1
139
- expect(roots.first.auto_include_context.models).to match_array(roots)
140
- end
141
-
142
- it "sets the AutoIncludeContext for child nested associations" do
143
- expect(cars.map(&:auto_include_context).uniq.size).to eq 1
144
- expect(cars.first.auto_include_context.models).to match_array(cars)
145
- end
146
- end
147
-
148
- def create_mock_models(num)
149
- num.times.map { create_mock_model }
150
- end
151
-
152
- def create_mock_model(associations = {})
153
- model = AutoIncludeContextMockModel.new
154
- associations.each do |association, models|
155
- allow(model).to receive(:association).with(association) do
156
- OpenStruct.new(target: models)
157
- end
158
- end
159
- model
160
- end
161
-
162
- AutoIncludeContextMockModel = Struct.new(:auto_include_context)
163
- end
164
- end
@@ -1,787 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Goldiloader do
6
- let!(:author1) do
7
- User.create!(name: 'author1') { |u| u.address = Address.new(city: 'author1-city') }
8
- end
9
-
10
- let!(:author2) do
11
- User.create!(name: 'author2') { |u| u.address = Address.new(city: 'author2-city') }
12
- end
13
-
14
- let!(:author3) do
15
- User.create!(name: 'author3') { |u| u.address = Address.new(city: 'author3-city') }
16
- end
17
-
18
- let!(:group1) { Group.create!(name: 'group1') }
19
-
20
- let!(:parent_tag1) { Tag.create!(name: 'parent1') { |t| t.owner = group1 } }
21
- let!(:child_tag1) { parent_tag1.children.create!(name: 'parent1-child1') { |t| t.owner = author1 } }
22
- let!(:child_tag2) { parent_tag1.children.create!(name: 'parent1-child2') { |t| t.owner = group1 } }
23
- let!(:parent_tag2) { Tag.create!(name: 'parent2') { |t| t.owner = group1 } }
24
- let!(:child_tag3) { parent_tag2.children.create!(name: 'parent2-child1') { |t| t.owner = author2 } }
25
-
26
- let!(:blog1) do
27
- blog1 = Blog.create!(name: 'blog1')
28
-
29
- blog1.posts.create!(title: 'blog1-post1') do |post|
30
- post.author = author1
31
- post.tags << child_tag1 << child_tag2
32
- end
33
-
34
- blog1.posts.create!(title: 'blog1-post2') do |post|
35
- post.author = author2
36
- post.tags << child_tag1
37
- end
38
-
39
- blog1
40
- end
41
-
42
- let!(:blog2) do
43
- blog2 = Blog.create!(name: 'blog2')
44
-
45
- blog2.posts.create!(title: 'blog2-post1') do |post|
46
- post.author = author3
47
- post.tags << child_tag1
48
- end
49
-
50
- blog2.posts.create!(title: 'blog2-post2') do |post|
51
- post.author = author1
52
- post.tags << child_tag3
53
- end
54
-
55
- blog2
56
- end
57
-
58
- before do
59
- [Address, Blog, Post, Tag, User, Group].each do |klass|
60
- allow(klass).to receive(:find_by_sql).and_call_original
61
- end
62
-
63
- ActiveRecord::Base.logger.info('Test setup complete')
64
- end
65
-
66
- it "auto eager loads has_many associations" do
67
- blogs = Blog.order(:name).to_a
68
-
69
- # Sanity check that associations aren't loaded yet
70
- blogs.each do |blog|
71
- expect(blog.association(:posts)).to_not be_loaded
72
- end
73
-
74
- # Force the first blogs first post to load
75
- blogs.first.posts.to_a
76
-
77
- blogs.each do |blog|
78
- expect(blog.association(:posts)).to be_loaded
79
- end
80
-
81
- expect(blogs.first.posts.map(&:title)).to match_array(['blog1-post1', 'blog1-post2'])
82
- expect(blogs.second.posts.map(&:title)).to match_array(['blog2-post1', 'blog2-post2'])
83
-
84
- expect(Post).to have_received(:find_by_sql).once
85
- end
86
-
87
- it "auto eager loads belongs_to associations" do
88
- posts = Post.order(:title).to_a
89
-
90
- # Sanity check that associations aren't loaded yet
91
- posts.each do |blog|
92
- expect(blog.association(:blog)).to_not be_loaded
93
- end
94
-
95
- # Force the first post's blog to load
96
- posts.first.blog
97
-
98
- posts.each do |blog|
99
- expect(blog.association(:blog)).to be_loaded
100
- end
101
-
102
- expect(posts.map(&:blog).map(&:name)).to eq(['blog1', 'blog1', 'blog2', 'blog2'])
103
- expect(Blog).to have_received(:find_by_sql).once
104
- end
105
-
106
- it "auto eager loads has_one associations" do
107
- users = User.order(:name).to_a
108
-
109
- # Sanity check that associations aren't loaded yet
110
- users.each do |user|
111
- expect(user.association(:address)).to_not be_loaded
112
- end
113
-
114
- # Force the first user's address to load
115
- users.first.address
116
-
117
- users.each do |blog|
118
- expect(blog.association(:address)).to be_loaded
119
- end
120
-
121
- expect(users.map(&:address).map(&:city)).to match_array(['author1-city', 'author2-city', 'author3-city'])
122
- expect(Address).to have_received(:find_by_sql).once
123
- end
124
-
125
- it "auto eager loads nested associations" do
126
- blogs = Blog.order(:name).to_a
127
- blogs.first.posts.to_a.first.author
128
-
129
- blogs.flat_map(&:posts).each do |blog|
130
- expect(blog.association(:author)).to be_loaded
131
- end
132
-
133
- expect(blogs.first.posts.first.author).to eq author1
134
- expect(blogs.first.posts.second.author).to eq author2
135
- expect(blogs.second.posts.first.author).to eq author3
136
- expect(blogs.second.posts.second.author).to eq author1
137
- expect(Post).to have_received(:find_by_sql).once
138
- end
139
-
140
- it "auto eager loads has_many through associations" do
141
- blogs = Blog.order(:name).to_a
142
- blogs.first.authors.to_a
143
-
144
- blogs.each do |blog|
145
- expect(blog.association(:authors)).to be_loaded
146
- end
147
-
148
- expect(blogs.first.authors).to match_array([author1, author2])
149
- expect(blogs.second.authors).to match_array([author3, author1])
150
- expect(User).to have_received(:find_by_sql).once
151
- end
152
-
153
- it "auto eager loads nested has_many through associations" do
154
- blogs = Blog.order(:name).to_a
155
- blogs.first.addresses.to_a
156
-
157
- blogs.each do |blog|
158
- expect(blog.association(:addresses)).to be_loaded
159
- end
160
-
161
- expect(blogs.first.addresses).to match_array([author1, author2].map(&:address))
162
- expect(blogs.second.addresses).to match_array([author3, author1].map(&:address))
163
- expect(Address).to have_received(:find_by_sql).once
164
- end
165
-
166
- it "auto eager loads associations when the model is loaded via find" do
167
- blog = Blog.find(blog1.id)
168
- blog.posts.to_a.first.author
169
-
170
- blog.posts.each do |blog|
171
- expect(blog.association(:author)).to be_loaded
172
- end
173
- end
174
-
175
- it "auto eager loads polymorphic associations" do
176
- tags = Tag.where('parent_id IS NOT NULL').order(:name).to_a
177
- tags.first.owner
178
-
179
- tags.each do |tag|
180
- expect(tag.association(:owner)).to be_loaded
181
- end
182
-
183
- expect(tags.first.owner).to eq author1
184
- expect(tags.second.owner).to eq group1
185
- expect(tags.third.owner).to eq author2
186
- end
187
-
188
- it "auto eager loads associations of polymorphic associations" do
189
- tags = Tag.where('parent_id IS NOT NULL').order(:name).to_a
190
- users = tags.map(&:owner).select {|owner| owner.is_a?(User) }.sort_by(&:name)
191
- users.first.posts.to_a
192
-
193
- users.each do |user|
194
- expect(user.association(:posts)).to be_loaded
195
- end
196
-
197
- expect(users.first.posts).to eq Post.where(author_id: author1.id)
198
- expect(users.second.posts).to eq Post.where(author_id: author2.id)
199
- end
200
-
201
- it "only auto eager loads associations loaded through the same path" do
202
- root_tags = Tag.where(parent_id: nil).order(:name).to_a
203
- root_tags.first.children.to_a
204
-
205
- # Make sure we loaded all child tags
206
- root_tags.each do |tag|
207
- expect(tag.association(:children)).to be_loaded
208
- end
209
-
210
- # Force a load of a root tag's owner
211
- root_tags.first.owner
212
-
213
- # All root tag owners should be loaded
214
- root_tags.each do |tag|
215
- expect(tag.association(:owner)).to be_loaded
216
- end
217
-
218
- # Child tag owners should not be loaded
219
- child_tags = root_tags.flat_map(&:children)
220
- child_tags.each do |tag|
221
- expect(tag.association(:owner)).to_not be_loaded
222
- end
223
- end
224
-
225
- it "auto eager loads associations that have been overridden" do
226
- blogs = Blog.order(:name).to_a
227
-
228
- blogs.first.association(:posts_overridden).load_target
229
-
230
- blogs.each do |blog|
231
- expect(blog.association(:posts_overridden)).to be_loaded
232
- end
233
- end
234
-
235
- it "marks auto eager loaded models as read only when the association is read only" do
236
- blog = Blog.first!
237
- post = blog.read_only_posts.to_a.first
238
- expect { post.save! }.to raise_error(ActiveRecord::ReadOnlyRecord)
239
- end
240
-
241
- it "doesn't mark auto eager loaded models as read only when the association is not read only" do
242
- blog = Blog.first!
243
- post = blog.posts.to_a.first
244
- expect { post.save! }.to_not raise_error
245
- end
246
-
247
- context "with manual eager loading" do
248
- let(:blogs) { Blog.order(:name).send(load_method, :posts).to_a }
249
-
250
- before do
251
- blogs.first.posts.to_a.first.author
252
- end
253
-
254
- shared_examples "it auto-eager loads associations of manually eager loaded associations" do
255
- specify do
256
- blogs.flat_map(&:posts).drop(1).each do |blog|
257
- expect(blog.association(:author)).to be_loaded
258
- end
259
-
260
- expect(blogs.first.posts.first.author).to eq author1
261
- expect(blogs.first.posts.second.author).to eq author2
262
- expect(blogs.second.posts.first.author).to eq author3
263
- expect(blogs.second.posts.second.author).to eq author1
264
- expect(Post).to have_received(:find_by_sql).at_most(:once)
265
- end
266
- end
267
-
268
- context "via includes" do
269
- let(:load_method) { :includes }
270
-
271
- it_behaves_like "it auto-eager loads associations of manually eager loaded associations"
272
- end
273
-
274
- context "via eager_load" do
275
- let(:load_method) { :eager_load }
276
-
277
- it_behaves_like "it auto-eager loads associations of manually eager loaded associations"
278
- end
279
-
280
- context "via preload" do
281
- let(:load_method) { :preload }
282
-
283
- it_behaves_like "it auto-eager loads associations of manually eager loaded associations"
284
- end
285
- end
286
-
287
- context "with associations that can't be eager loaded" do
288
- let(:blogs) { Blog.order(:name).to_a }
289
-
290
- before do
291
- blog1.posts.create!(title: 'blog1-post3', author: author1)
292
- blog2.posts.create!(title: 'blog2-post3', author: author1)
293
- end
294
-
295
- shared_examples "it doesn't auto eager the association" do |association_name|
296
- specify do
297
- blogs.drop(1).each do |blog|
298
- expect(blog.association(association_name)).to_not be_loaded
299
- end
300
- end
301
- end
302
-
303
- shared_examples "it auto eager loads the association" do |association_name|
304
- specify do
305
- blogs.drop(1).each do |blog|
306
- expect(blog.association(association_name)).to be_loaded
307
- end
308
- end
309
- end
310
-
311
- context "associations with a limit" do
312
- before do
313
- blogs.first.limited_posts.to_a
314
- end
315
-
316
- it "applies the limit correctly" do
317
- expect(blogs.first.limited_posts.to_a.size).to eq 2
318
- end
319
-
320
- it_behaves_like "it doesn't auto eager the association", :limited_posts
321
- end
322
-
323
- context "associations with a group" do
324
- before do
325
- blogs.first.grouped_posts.to_a
326
- end
327
-
328
- it "applies the group correctly" do
329
- expect(blogs.first.grouped_posts.to_a.size).to eq 1
330
- end
331
-
332
- it_behaves_like "it doesn't auto eager the association", :grouped_posts
333
- end
334
-
335
- context "associations with an offset" do
336
- before do
337
- blogs.first.offset_posts.to_a
338
- end
339
-
340
- it "applies the offset correctly" do
341
- expect(blogs.first.offset_posts.to_a.size).to eq 1
342
- end
343
-
344
- it_behaves_like "it doesn't auto eager the association", :offset_posts
345
- end
346
-
347
- if ActiveRecord::VERSION::MAJOR >= 4
348
- context "associations with an overridden from" do
349
- before do
350
- blogs.first.from_posts.to_a
351
- end
352
-
353
- it "applies the from correctly" do
354
- expect(blogs.first.from_posts.to_a.size).to eq 1
355
- end
356
-
357
- it_behaves_like "it doesn't auto eager the association", :from_posts
358
- end
359
- end
360
-
361
- if Goldiloader::Compatibility.association_finder_sql_enabled?
362
- context "associations with finder_sql" do
363
- before do
364
- blogs.first.finder_sql_posts.to_a
365
- end
366
-
367
- it "applies the finder_sql correctly" do
368
- expect(blogs.first.finder_sql_posts.to_a.size).to eq 1
369
- end
370
-
371
- it_behaves_like "it doesn't auto eager the association", :finder_sql_posts
372
- end
373
- end
374
-
375
- if ActiveRecord::VERSION::MAJOR >= 4
376
- context "associations with a join" do
377
- before do
378
- blogs.first.posts_ordered_by_author.to_a
379
- end
380
-
381
- it "applies the join correctly" do
382
- sorted_post_authors = blogs.first.posts.map(&:author).map(&:name).sort
383
- expect(blogs.first.posts_ordered_by_author.map(&:author).map(&:name)).to eq sorted_post_authors
384
- end
385
-
386
- if Goldiloader::Compatibility.joins_eager_loadable?
387
- it_behaves_like "it auto eager loads the association", :posts_ordered_by_author
388
- else
389
- it_behaves_like "it doesn't auto eager the association", :posts_ordered_by_author
390
- end
391
- end
392
-
393
- context "associations with a join in a has_many_through" do
394
- before do
395
- blogs.first.authors_with_join.to_a
396
- end
397
-
398
- it "applies the join correctly" do
399
- sorted_post_cities = blogs.first.posts.map(&:author).map(&:address).map(&:city).sort
400
- expect(blogs.first.posts_ordered_by_author.map(&:author).map(&:address).map(&:city)).to eq sorted_post_cities
401
- end
402
-
403
- if Goldiloader::Compatibility.joins_eager_loadable?
404
- it_behaves_like "it auto eager loads the association", :authors_with_join
405
- else
406
- it_behaves_like "it doesn't auto eager the association", :authors_with_join
407
- end
408
- end
409
- end
410
-
411
- if Goldiloader::Compatibility.unscope_query_method_enabled?
412
- context "associations with an unscoped" do
413
- let(:authors) { User.order(:id).to_a }
414
-
415
- before do
416
- author1.address.update_attributes!(city: 'Boston')
417
- author2.address.update_attributes!(city: 'Philadelphia')
418
- author3.address.update_attributes!(city: 'Philadelphia')
419
- authors.first.scoped_address_with_default_scope_remove
420
- end
421
-
422
- it "applies the unscope correctly" do
423
- expect(authors.first.scoped_address_with_default_scope_remove).to be_present
424
- end
425
-
426
- it "auto eager loads the association" do
427
- authors.drop(1).each do |author|
428
- expect(author.association(:scoped_address_with_default_scope_remove)).to be_loaded
429
- end
430
- end
431
- end
432
- end
433
-
434
- if ActiveRecord::VERSION::MAJOR < 4
435
- context "unique_tags_has_and_belongs associations with a uniq" do
436
- let!(:post1) do
437
- Post.create! { |post| post.tags << child_tag1 << child_tag1 << child_tag3 }
438
- end
439
-
440
- let!(:post2) do
441
- Post.create! { |post| post.tags << child_tag1 << child_tag1 << child_tag2 }
442
- end
443
-
444
- let(:posts) { Post.where(id: [post1.id, post2.id]).order(:id).to_a }
445
-
446
- before do
447
- posts.first.unique_tags_has_and_belongs.to_a
448
- end
449
-
450
- it "applies the uniq correctly" do
451
- expect(posts.first.unique_tags_has_and_belongs.to_a.size).to eq 2
452
- end
453
-
454
- it "doesn't auto eager the association" do
455
- posts.drop(1).each do |author|
456
- expect(author.association(:unique_tags_has_and_belongs)).to_not be_loaded
457
- end
458
- end
459
- end
460
- end
461
-
462
- if ActiveRecord::VERSION::MAJOR >= 4
463
- context "associations with an instance dependent scope" do
464
- before do
465
- blogs.first.instance_dependent_posts.to_a
466
- end
467
-
468
- it "applies the scope correctly" do
469
- expect(blogs.first.instance_dependent_posts.to_a).to match_array(blogs.first.posts)
470
- end
471
-
472
- it_behaves_like "it doesn't auto eager the association", :instance_dependent_posts
473
- end
474
- end
475
- end
476
-
477
- context "associations with a uniq" do
478
- let!(:post1) do
479
- Post.create! { |post| post.tags << child_tag1 << child_tag1 << child_tag3 }
480
- end
481
-
482
- let!(:post2) do
483
- Post.create! { |post| post.tags << child_tag1 << child_tag1 << child_tag2 }
484
- end
485
-
486
- let(:posts) { Post.where(id: [post1.id, post2.id]).order(:id).to_a }
487
-
488
- before do
489
- posts.first.unique_tags.to_a
490
- end
491
-
492
- it "applies the uniq correctly" do
493
- expect(posts.first.unique_tags.to_a).to match_array([child_tag1, child_tag3])
494
- end
495
-
496
- it "auto eager loads the association" do
497
- posts.each do |blog|
498
- expect(blog.association(:unique_tags)).to be_loaded
499
- end
500
- end
501
- end
502
-
503
- context "polymorphic associations with nil" do
504
- let!(:user) { User.create! }
505
- let!(:group) { Group.create! }
506
-
507
- let!(:post1) do
508
- Post.create! { |post| post.owner = user }
509
- end
510
-
511
- let!(:post2) do
512
- Post.create! { |post| post.owner = group }
513
- end
514
-
515
- let!(:post3) do
516
- Post.create!
517
- end
518
-
519
- let(:posts) { Post.where(id: [post1, post2, post3].map(&:id)).order(:id).to_a }
520
-
521
- before do
522
- posts.first.owner
523
- end
524
-
525
- it "loads the association correctly" do
526
- expect(posts.map(&:owner)).to eq [user, group, nil]
527
- end
528
-
529
- it "auto eager loads the association" do
530
- posts.select(&:owner_id).each do |post|
531
- expect(post.association(:owner)).to be_loaded
532
- end
533
- end
534
- end
535
-
536
- context "when a model is destroyed" do
537
- let!(:posts) { Post.where(blog_id: blog1.id).to_a }
538
- let(:destroyed_post) { posts.first }
539
- let(:other_post) { posts.last }
540
-
541
- before do
542
- blog_after_destroy = nil
543
- destroyed_post.define_singleton_method(:after_post_destroy) do
544
- blog_after_destroy = self.blog
545
- end
546
- destroyed_post.destroy
547
- @blog_after_destroy = blog_after_destroy
548
- end
549
-
550
- it "can load associations in after_destroy callbacks" do
551
- expect(@blog_after_destroy).to eq blog1
552
- end
553
-
554
- it "auto eager loads the associaton on other models" do
555
- expect(other_post.association(:blog)).to be_loaded
556
- end
557
- end
558
-
559
- context "when a has_many association has in-memory changes" do
560
- let!(:blogs) { Blog.order(:name).to_a }
561
- let(:blog) { blogs.first }
562
- let(:other_blog) { blogs.last }
563
-
564
- before do
565
- blog.posts.create(title: 'blog1-new-post')
566
- end
567
-
568
- it "returns the correct models for the modified has_many association" do
569
- expect(blog.posts).to match_array Post.where(blog_id: blog.id)
570
- end
571
-
572
- it "doesn't auto eager load peers when accessing the modified has_many association" do
573
- blog.posts.to_a
574
- expect(other_blog.association(:posts)).to_not be_loaded
575
- end
576
-
577
- it "returns the correct models for the modified has_many association when accessing a peer" do
578
- other_blog.posts.to_a
579
- expect(blog.posts).to match_array Post.where(blog_id: blog.id)
580
- end
581
- end
582
-
583
- context "when a has_many through association has in-memory changes" do
584
- let!(:posts) { Post.order(:title).to_a }
585
- let(:post) { posts.first }
586
- let(:other_post) { posts.last }
587
-
588
- before do
589
- tag = Tag.create(name: 'new-tag')
590
- post.post_tags.create(tag: tag)
591
- end
592
-
593
- it "returns the correct models for the modified has_many through association" do
594
- expect(post.tags).to match_array PostTag.where(post_id: post.id).includes(:tag).map(&:tag)
595
- end
596
-
597
- it "doesn't auto eager load peers when accessing the modified has_many through association" do
598
- post.tags.to_a
599
- expect(other_post.association(:tags)).to_not be_loaded
600
- end
601
-
602
- it "returns the correct models for the modified has_many through association when accessing a peer" do
603
- other_post.tags.to_a
604
- expect(post.tags).to match_array PostTag.where(post_id: post.id).includes(:tag).map(&:tag)
605
- end
606
- end
607
-
608
- context "with fully_load false" do
609
-
610
- it "doesn't auto eager loads a has_many association when size is called" do
611
- blogs = Blog.order(:name).to_a
612
- blogs.first.posts.size
613
-
614
- blogs.each do |blog|
615
- expect(blog.association(:posts)).to_not be_loaded
616
- end
617
- end
618
-
619
- it "doesn't auto eager loads a has_many association when exists? is called" do
620
- blogs = Blog.order(:name).to_a
621
- blogs.first.posts.exists?
622
-
623
- blogs.each do |blog|
624
- expect(blog.association(:posts)).to_not be_loaded
625
- end
626
- end
627
-
628
- it "doesn't auto eager loads a has_many association when last is called" do
629
- blogs = Blog.order(:name).to_a
630
- blogs.first.posts.last
631
-
632
- blogs.each do |blog|
633
- expect(blog.association(:posts)).to_not be_loaded
634
- end
635
- end
636
-
637
- it "doesn't auto eager loads a has_many association when ids is called" do
638
- blogs = Blog.order(:name).to_a
639
- blogs.first.post_ids
640
-
641
- blogs.each do |blog|
642
- expect(blog.association(:posts)).to_not be_loaded
643
- end
644
- end
645
- end
646
-
647
- context "with fully_load true" do
648
-
649
- it "auto eager loads a has_many association when size is called" do
650
- blogs = Blog.order(:name).to_a
651
- blogs.first.posts_fully_load.size
652
-
653
- blogs.each do |blog|
654
- expect(blog.association(:posts_fully_load)).to be_loaded
655
- end
656
- end
657
-
658
- it "auto eager loads a has_many association when exists? is called" do
659
- blogs = Blog.order(:name).to_a
660
- blogs.first.posts_fully_load.exists?
661
-
662
- blogs.each do |blog|
663
- expect(blog.association(:posts_fully_load)).to be_loaded
664
- end
665
- end
666
-
667
- it "doesn't auto eager load a has_many association when exists? is called with arguments" do
668
- blogs = Blog.order(:name).to_a
669
- blogs.first.posts_fully_load.exists?(false)
670
-
671
- blogs.each do |blog|
672
- expect(blog.association(:posts_fully_load)).to_not be_loaded
673
- end
674
- end
675
-
676
- it "auto eager loads a has_many association when last is called" do
677
- blogs = Blog.order(:name).to_a
678
- blogs.first.posts_fully_load.last
679
-
680
- blogs.each do |blog|
681
- expect(blog.association(:posts_fully_load)).to be_loaded
682
- end
683
- end
684
-
685
- it "auto eager loads a has_many association when ids is called" do
686
- blogs = Blog.order(:name).to_a
687
- blogs.first.posts_fully_load_ids
688
-
689
- blogs.each do |blog|
690
- expect(blog.association(:posts_fully_load)).to be_loaded
691
- end
692
- end
693
-
694
- end
695
-
696
- context "with auto_include disabled" do
697
-
698
- it "doesn't auto eager load has_many associations" do
699
- blogs = Blog.order(:name).to_a
700
-
701
- # Force the first blogs first post to load
702
- posts = blogs.first.posts_without_auto_include.to_a
703
- expect(posts).to match_array Post.where(blog_id: blogs.first.id)
704
-
705
- blogs.drop(1).each do |blog|
706
- expect(blog.association(:posts_without_auto_include)).to_not be_loaded
707
- end
708
- end
709
-
710
- it "doesn't auto eager load has_one associations" do
711
- users = User.order(:name).to_a
712
-
713
- # Force the first user's address to load
714
- user = users.first
715
- address = user.address_without_auto_include
716
- expect(address).to eq Address.where(user_id: user.id).first
717
-
718
- users.drop(1).each do |blog|
719
- expect(blog.association(:address_without_auto_include)).to_not be_loaded
720
- end
721
- end
722
-
723
- it "doesn't auto eager load belongs_to associations" do
724
- posts = Post.order(:title).to_a
725
- # Force the first post's blog to load
726
- post = posts.first
727
- blog = post.blog_without_auto_include
728
- expect(blog).to eq Blog.where(id: post.blog_id).first
729
-
730
- posts.drop(1).each do |blog|
731
- expect(blog.association(:blog_without_auto_include)).to_not be_loaded
732
- end
733
- end
734
-
735
- it "doesn't auto eager load has_and_belongs_to_many associations" do
736
- posts = Post.all.to_a
737
-
738
- # Force the first post's tags to load
739
- posts.first.tags_without_auto_include.to_a
740
-
741
- posts.drop(1).each do |post|
742
- expect(post.association(:tags_without_auto_include)).to_not be_loaded
743
- end
744
- end
745
-
746
- it "still auto eager loads nested associations" do
747
- posts = Post.order(:title).to_a
748
- # Force the first post's blog to load
749
- blog = posts.first.blog_without_auto_include
750
-
751
- # Load another blogs posts
752
- other_blog = posts.last.blog_without_auto_include
753
- other_blog.posts.to_a
754
-
755
- blog.posts.to_a.first.tags.to_a
756
-
757
- blog.posts.each do |post|
758
- expect(post.association(:tags)).to be_loaded
759
- end
760
-
761
- other_blog.posts.each do |post|
762
- expect(post.association(:tags)).to_not be_loaded
763
- end
764
- end
765
- end
766
-
767
- describe "CollectionProxy#exists?" do
768
- it "returns true for collections with values" do
769
- expect(parent_tag1.children).to exist
770
- end
771
-
772
- it "returns false for collections without values" do
773
- expect(child_tag1.children).not_to exist
774
- end
775
-
776
- if Goldiloader::Compatibility::RAILS_3
777
- # Make sure we mimic the broken behavior of Rails 3
778
- it "returns true for new models with empty associations" do
779
- expect(Tag.new.children).to exist
780
- end
781
- else
782
- it "returns false for new models with empty associations" do
783
- expect(Tag.new.children).not_to exist
784
- end
785
- end
786
- end
787
- end