goldiloader 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
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