composite_primary_keys 8.1.0 → 8.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +642 -625
  3. data/README.rdoc +5 -2
  4. data/lib/composite_primary_keys.rb +115 -115
  5. data/lib/composite_primary_keys/associations/association.rb +23 -23
  6. data/lib/composite_primary_keys/associations/association_scope.rb +73 -73
  7. data/lib/composite_primary_keys/associations/collection_association.rb +14 -14
  8. data/lib/composite_primary_keys/associations/has_many_association.rb +69 -69
  9. data/lib/composite_primary_keys/associations/join_dependency.rb +87 -87
  10. data/lib/composite_primary_keys/associations/preloader/association.rb +90 -90
  11. data/lib/composite_primary_keys/associations/singular_association.rb +18 -18
  12. data/lib/composite_primary_keys/attribute_methods.rb +9 -9
  13. data/lib/composite_primary_keys/attribute_methods/dirty.rb +29 -29
  14. data/lib/composite_primary_keys/attribute_methods/read.rb +24 -24
  15. data/lib/composite_primary_keys/attribute_methods/write.rb +30 -30
  16. data/lib/composite_primary_keys/attribute_set/builder.rb +19 -19
  17. data/lib/composite_primary_keys/base.rb +129 -135
  18. data/lib/composite_primary_keys/composite_arrays.rb +43 -43
  19. data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +2 -3
  20. data/lib/composite_primary_keys/core.rb +60 -60
  21. data/lib/composite_primary_keys/persistence.rb +56 -56
  22. data/lib/composite_primary_keys/relation.rb +68 -68
  23. data/lib/composite_primary_keys/relation/calculations.rb +78 -78
  24. data/lib/composite_primary_keys/relation/finder_methods.rb +179 -179
  25. data/lib/composite_primary_keys/sanitization.rb +52 -52
  26. data/lib/composite_primary_keys/validations/uniqueness.rb +36 -36
  27. data/lib/composite_primary_keys/version.rb +8 -8
  28. data/tasks/databases/sqlserver.rake +27 -27
  29. data/test/abstract_unit.rb +114 -113
  30. data/test/connections/databases.example.yml +25 -25
  31. data/test/connections/native_sqlserver/connection.rb +11 -11
  32. data/test/fixtures/db_definitions/mysql.sql +218 -218
  33. data/test/fixtures/db_definitions/postgresql.sql +220 -220
  34. data/test/fixtures/db_definitions/sqlite.sql +206 -206
  35. data/test/fixtures/db_definitions/sqlserver.drop.sql +91 -91
  36. data/test/fixtures/db_definitions/sqlserver.sql +226 -226
  37. data/test/fixtures/employee.rb +11 -11
  38. data/test/fixtures/salary.rb +5 -5
  39. data/test/test_associations.rb +341 -340
  40. data/test/test_attributes.rb +60 -60
  41. data/test/test_create.rb +157 -157
  42. data/test/test_delete.rb +158 -158
  43. data/test/test_delete_all.rb +33 -28
  44. data/test/test_enum.rb +21 -21
  45. data/test/test_equal.rb +26 -26
  46. data/test/test_find.rb +119 -118
  47. data/test/test_habtm.rb +117 -113
  48. data/test/test_polymorphic.rb +27 -26
  49. data/test/test_tutorial_example.rb +25 -25
  50. metadata +44 -2
@@ -1,11 +1,11 @@
1
- class Employee < ActiveRecord::Base
2
- belongs_to :department, :foreign_key => [:department_id, :location_id]
3
- has_many :comments, :as => :person
4
- has_and_belongs_to_many :groups
5
- has_many :salaries,
6
- :primary_key => [:id, :location_id],
7
- :foreign_key => [:employee_id, :location_id]
8
- has_one :one_salary, :class_name => "Salary",
9
- :primary_key => [:id, :location_id],
10
- :foreign_key => [:employee_id, :location_id]
11
- end
1
+ class Employee < ActiveRecord::Base
2
+ belongs_to :department, :foreign_key => [:department_id, :location_id]
3
+ has_many :comments, :as => :person
4
+ has_and_belongs_to_many :groups
5
+ has_many :salaries,
6
+ :primary_key => [:id, :location_id],
7
+ :foreign_key => [:employee_id, :location_id]
8
+ has_one :one_salary, :class_name => "Salary",
9
+ :primary_key => [:id, :location_id],
10
+ :foreign_key => [:employee_id, :location_id]
11
+ end
@@ -1,5 +1,5 @@
1
- class Salary < ActiveRecord::Base
2
- belongs_to :employee,
3
- :primary_key => [:id, :location_id],
4
- :foreign_key => [:employee_id, :location_id]
5
- end
1
+ class Salary < ActiveRecord::Base
2
+ belongs_to :employee,
3
+ :primary_key => [:id, :location_id],
4
+ :foreign_key => [:employee_id, :location_id]
5
+ end
@@ -1,340 +1,341 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class TestAssociations < ActiveSupport::TestCase
4
- fixtures :articles, :products, :tariffs, :product_tariffs, :suburbs, :streets, :restaurants,
5
- :dorms, :rooms, :room_attributes, :room_attribute_assignments, :students, :room_assignments, :users, :readings,
6
- :departments, :employees, :memberships, :membership_statuses
7
-
8
- def test_products
9
- assert_not_nil products(:first_product).product_tariffs
10
- assert_equal 2, products(:first_product).product_tariffs.length
11
- assert_not_nil products(:first_product).tariffs
12
- assert_equal 2, products(:first_product).tariffs.length
13
- end
14
-
15
- def test_product_tariffs
16
- assert_not_nil product_tariffs(:first_flat).product
17
- assert_not_nil product_tariffs(:first_flat).tariff
18
- assert_equal Product, product_tariffs(:first_flat).product.class
19
- assert_equal Tariff, product_tariffs(:first_flat).tariff.class
20
- end
21
-
22
- def test_tariffs
23
- assert_not_nil tariffs(:flat).product_tariffs
24
- assert_equal 1, tariffs(:flat).product_tariffs.length
25
- assert_not_nil tariffs(:flat).products
26
- assert_equal 1, tariffs(:flat).products.length
27
- end
28
-
29
- # Its not generating the instances of associated classes from the rows
30
- def test_find_includes
31
- # Old style
32
- products = Product.includes(:product_tariffs).all
33
- assert_equal(3, products.length)
34
- assert_equal(3, products.inject(0) {|sum, product| sum + product.product_tariffs.length})
35
-
36
- # New style
37
- products = Product.includes(:product_tariffs)
38
- assert_equal(3, products.length)
39
- assert_equal(3, products.inject(0) {|sum, product| sum + product.product_tariffs.length})
40
- end
41
-
42
- def test_find_includes_eager_loading
43
- product = products(:second_product)
44
- product_tarrif = product_tariffs(:second_free)
45
-
46
- # First get a legitimate product tarrif
47
- products = Product.includes(:product_tariffs).where('product_tariffs.product_id = ?', product.id).references(:product_tariffs)
48
- assert_equal(1, products.length)
49
- assert_equal(product, products.first)
50
- assert_equal([product_tarrif], products.first.product_tariffs)
51
- end
52
-
53
- def test_find_eager_loading_none
54
- product = products(:third_product)
55
-
56
- products = Product.includes(:product_tariffs).where(:id => product.id).references(:product_tariffs)
57
- assert_equal(1, products.length)
58
- assert_equal(product, products.first)
59
- assert_empty(products.first.product_tariffs)
60
- end
61
-
62
- def test_find_includes_tariffs
63
- # Old style
64
- tariffs = Tariff.includes(:product_tariffs)
65
- assert_equal(3, tariffs.length)
66
- assert_equal(3, tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length})
67
-
68
- # New style
69
- tariffs = Tariff.includes(:product_tariffs)
70
- assert_equal(3, tariffs.length)
71
- assert_equal(3, tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length})
72
- end
73
-
74
- def test_has_one_association_is_not_cached_to_where_it_returns_the_wrong_one
75
- engineering = departments(:engineering)
76
- engineering_head = engineering.head
77
-
78
- accounting = departments(:accounting)
79
- accounting_head = accounting.head
80
-
81
- refute_equal accounting_head, engineering_head
82
- end
83
-
84
- def test_has_one_association_primary_key_and_foreign_key_are_present
85
- steve = employees(:steve)
86
- steve_salary = steve.create_one_salary(year: "2015", month: "1")
87
-
88
- jill = employees(:jill)
89
- jill_salary = jill.create_one_salary(year: "2015", month: "1")
90
-
91
- steve_salary.reload
92
- jill_salary.reload
93
- assert_equal(steve.id, steve_salary.employee_id)
94
- assert_equal(1, steve_salary.location_id)
95
- assert_equal(jill.id, jill_salary.employee_id)
96
- assert_equal(1, jill_salary.location_id)
97
- end
98
-
99
- def test_has_many_association_is_not_cached_to_where_it_returns_the_wrong_ones
100
- engineering = departments(:engineering)
101
- engineering_employees = engineering.employees
102
-
103
- accounting = departments(:accounting)
104
- accounting_employees = accounting.employees
105
-
106
- refute_equal accounting_employees, engineering_employees
107
- end
108
-
109
- def test_has_many_association_primary_key_and_foreign_key_are_present
110
- steve = employees(:steve)
111
- steve_salary = steve.salaries.create(year: 2015, month: 1)
112
-
113
- jill = employees(:jill)
114
- jill_salary = jill.salaries.create(year: 2015, month: 1)
115
-
116
- steve_salary.reload
117
- jill_salary.reload
118
- assert_equal(steve.id, steve_salary.employee_id)
119
- assert_equal(1, steve_salary.location_id)
120
- assert_equal(jill.id, jill_salary.employee_id)
121
- assert_equal(1, jill_salary.location_id)
122
- end
123
-
124
- def test_belongs_to_association_primary_key_and_foreign_key_are_present
125
- salary_01 = Salary.new(year: 2015, month: 1, employee_id: 5, location_id: 1)
126
- employee_01 = salary_01.create_employee
127
- salary_02 = Salary.new(year: 2015, month: 1, employee_id: 6, location_id: 1)
128
- employee_02 = salary_02.create_employee
129
-
130
- employee_01.reload
131
- employee_02.reload
132
-
133
- assert_equal(5, employee_01.id)
134
- assert_equal(1, employee_01.location_id)
135
- assert_equal(6, employee_02.id)
136
- assert_equal(1, employee_02.location_id)
137
- end
138
-
139
- def test_find_includes_product_tariffs_product
140
- # Old style
141
- product_tariffs = ProductTariff.includes(:product)
142
- assert_not_nil(product_tariffs)
143
- assert_equal(3, product_tariffs.length)
144
-
145
- # New style
146
- product_tariffs = ProductTariff.includes(:product)
147
- assert_not_nil(product_tariffs)
148
- assert_equal(3, product_tariffs.length)
149
- end
150
-
151
- def test_find_includes_product_tariffs_tariff
152
- # Old style
153
- product_tariffs = ProductTariff.includes(:tariff)
154
- assert_equal(3, product_tariffs.length)
155
-
156
- # New style
157
- product_tariffs = ProductTariff.includes(:tariff)
158
- assert_equal(3, product_tariffs.length)
159
- end
160
-
161
- def test_has_many_through
162
- products = Product.includes(:tariffs)
163
- assert_equal(3, products.length)
164
-
165
- tarrifs_length = products.inject(0) {|sum, product| sum + product.tariffs.length}
166
- assert_equal(3, tarrifs_length)
167
- end
168
-
169
- def test_new_style_includes_with_conditions
170
- product_tariff = ProductTariff.includes(:tariff).where('tariffs.amount < 5').references(:tariffs).first
171
- assert_equal(0, product_tariff.tariff.amount)
172
- end
173
-
174
- def test_find_product_includes
175
- products = Product.includes(:product_tariffs => :tariff)
176
- assert_equal(3, products.length)
177
-
178
- product_tariffs_length = products.inject(0) {|sum, product| sum + product.product_tariffs.length}
179
- assert_equal(3, product_tariffs_length)
180
- end
181
-
182
- def test_find_tariffs_includes
183
- tariffs = Tariff.includes(:product_tariffs => :product)
184
- assert_equal(3, tariffs.length)
185
-
186
- product_tariffs_length = tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length}
187
- assert_equal(3, product_tariffs_length)
188
- end
189
-
190
- def test_has_many_through_when_not_pre_loaded
191
- student = Student.first
192
- rooms = student.rooms
193
- assert_equal(1, rooms.size)
194
- assert_equal(1, rooms.first.dorm_id)
195
- assert_equal(1, rooms.first.room_id)
196
- end
197
-
198
- def test_has_many_through_when_through_association_is_composite
199
- dorm = Dorm.first
200
- assert_equal(3, dorm.rooms.length)
201
- assert_equal(1, dorm.rooms.first.room_attributes.length)
202
- assert_equal('type', dorm.rooms.first.room_attributes.first.name)
203
- end
204
-
205
- def test_associations_with_conditions
206
- suburb = Suburb.find([2, 1])
207
- assert_equal 2, suburb.streets.size
208
-
209
- suburb = Suburb.find([2, 1])
210
- assert_equal 1, suburb.first_streets.size
211
-
212
- suburb = Suburb.includes(:streets).find([2, 1])
213
- assert_equal 2, suburb.streets.size
214
-
215
- suburb = Suburb.includes(:first_streets).find([2, 1])
216
- assert_equal 1, suburb.first_streets.size
217
- end
218
-
219
- def test_composite_has_many_composites
220
- room = rooms(:branner_room_1)
221
- assert_equal(2, room.room_assignments.length)
222
- assert_equal(room_assignments(:jacksons_room), room.room_assignments[0])
223
- assert_equal(room_assignments(:bobs_room), room.room_assignments[1])
224
- end
225
-
226
- def test_composite_belongs_to_composite
227
- room_assignment = room_assignments(:jacksons_room)
228
- assert_equal(rooms(:branner_room_1), room_assignment.room)
229
- end
230
-
231
- def test_composite_belongs_to_changes
232
- room_assignment = room_assignments(:jacksons_room)
233
- room_assignment.room = rooms(:branner_room_2)
234
- # This was raising an error before:
235
- # TypeError: [:dorm_id, :room_id] is not a symbol
236
- # changes returns HashWithIndifferentAccess
237
- assert_equal({"room_id"=>[1, 2]}, room_assignment.changes)
238
-
239
- steve = employees(:steve)
240
- steve.department = departments(:engineering)
241
- # It was returning this before:
242
- # {"[:department_id, :location_id]"=>[nil, [2, 1]]}
243
- assert_equal({"department_id"=>[1, 2]}, steve.changes)
244
- end
245
-
246
- def test_composite_belongs_to__setting_to_nil
247
- room_assignment = room_assignments(:jacksons_room)
248
- # This was raising an error before:
249
- # NoMethodError: undefined method `length' for nil:NilClass
250
- assert_nothing_raised { room_assignment.room = nil }
251
- end
252
-
253
- def test_has_one_with_composite
254
- # In this case a regular model has_one composite model
255
- department = departments(:engineering)
256
- assert_not_nil(department.head)
257
- end
258
-
259
- def test_has_many_build__simple_key
260
- user = users(:santiago)
261
- reading = user.readings.build
262
- assert_equal user.id, reading.user_id
263
- assert_equal user, reading.user
264
- end
265
-
266
- def test_has_many_build__composite_key
267
- department = departments(:engineering)
268
- employee = department.employees.build
269
- assert_equal department.department_id, employee.department_id
270
- assert_equal department.location_id, employee.location_id
271
- assert_equal department, employee.department
272
- end
273
-
274
- def test_has_many_with_primary_key
275
- @membership = Membership.find([1, 1])
276
- assert_equal 2, @membership.readings.size
277
- end
278
-
279
- def test_has_many_with_composite_key
280
- # In this case a regular model (Dorm) has_many composite models (Rooms)
281
- dorm = dorms(:branner)
282
- assert_equal(3, dorm.rooms.length)
283
- assert_equal(1, dorm.rooms[0].room_id)
284
- assert_equal(2, dorm.rooms[1].room_id)
285
- assert_equal(3, dorm.rooms[2].room_id)
286
- end
287
-
288
- def test_joins_has_many_with_primary_key
289
- #@membership = Membership.find(:first, :joins => :readings, :conditions => { :readings => { :id => 1 } })
290
- @membership = Membership.joins(:readings).where(readings: { id: 1 }).first
291
-
292
- assert_equal [1, 1], @membership.id
293
- end
294
-
295
- def test_joins_has_one_with_primary_key
296
- @membership = Membership.joins(:readings).where(readings: { id: 2 }).first
297
-
298
- assert_equal [1, 1], @membership.id
299
- end
300
-
301
- def test_has_many_through_with_conditions_when_through_association_is_not_composite
302
- user = User.first
303
- assert_equal 1, user.articles.where("articles.name = ?", "Article One").size
304
- end
305
-
306
- def test_has_many_through_with_conditions_when_through_association_is_composite
307
- room = Room.first
308
- assert_equal 0, room.room_attributes.where("room_attributes.name != ?", "type").size
309
- end
310
-
311
- def test_has_many_through_on_custom_finder_when_through_association_is_composite_finder_when_through_association_is_not_composite
312
- user = User.first
313
- assert_equal(1, user.find_custom_articles.size)
314
- end
315
-
316
- def test_has_many_through_on_custom_finder_when_through_association_is_composite
317
- room = Room.first
318
- assert_equal(0, room.find_custom_room_attributes.size)
319
- end
320
-
321
- def test_has_many_with_primary_key_with_associations
322
- memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses)
323
- assert_equal(2, memberships.length)
324
- assert_equal([1,1], memberships[0].id)
325
- assert_equal([3,2], memberships[1].id)
326
- end
327
-
328
- def test_limitable_reflections
329
- memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses).limit(1)
330
- assert_equal(1, memberships.length)
331
- assert_equal([1,1], memberships[0].id)
332
- end
333
-
334
- def test_foreign_key_present_with_null_association_ids
335
- group = Group.new
336
- group.memberships.build
337
- associations = group.association_cache[:memberships]
338
- assert_equal(false, associations.send('foreign_key_present?'))
339
- end
340
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestAssociations < ActiveSupport::TestCase
4
+ fixtures :articles, :products, :tariffs, :product_tariffs, :suburbs, :streets, :restaurants,
5
+ :dorms, :rooms, :room_attributes, :room_attribute_assignments, :students, :room_assignments, :users, :readings,
6
+ :departments, :employees, :memberships, :membership_statuses
7
+
8
+ def test_products
9
+ assert_not_nil products(:first_product).product_tariffs
10
+ assert_equal 2, products(:first_product).product_tariffs.length
11
+ assert_not_nil products(:first_product).tariffs
12
+ assert_equal 2, products(:first_product).tariffs.length
13
+ end
14
+
15
+ def test_product_tariffs
16
+ assert_not_nil product_tariffs(:first_flat).product
17
+ assert_not_nil product_tariffs(:first_flat).tariff
18
+ assert_equal Product, product_tariffs(:first_flat).product.class
19
+ assert_equal Tariff, product_tariffs(:first_flat).tariff.class
20
+ end
21
+
22
+ def test_tariffs
23
+ assert_not_nil tariffs(:flat).product_tariffs
24
+ assert_equal 1, tariffs(:flat).product_tariffs.length
25
+ assert_not_nil tariffs(:flat).products
26
+ assert_equal 1, tariffs(:flat).products.length
27
+ end
28
+
29
+ # Its not generating the instances of associated classes from the rows
30
+ def test_find_includes
31
+ # Old style
32
+ products = Product.includes(:product_tariffs).all
33
+ assert_equal(3, products.length)
34
+ assert_equal(3, products.inject(0) {|sum, product| sum + product.product_tariffs.length})
35
+
36
+ # New style
37
+ products = Product.includes(:product_tariffs)
38
+ assert_equal(3, products.length)
39
+ assert_equal(3, products.inject(0) {|sum, product| sum + product.product_tariffs.length})
40
+ end
41
+
42
+ def test_find_includes_eager_loading
43
+ product = products(:second_product)
44
+ product_tarrif = product_tariffs(:second_free)
45
+
46
+ # First get a legitimate product tarrif
47
+ products = Product.includes(:product_tariffs).where('product_tariffs.product_id = ?', product.id).references(:product_tariffs)
48
+ assert_equal(1, products.length)
49
+ assert_equal(product, products.first)
50
+ assert_equal([product_tarrif], products.first.product_tariffs)
51
+ end
52
+
53
+ def test_find_eager_loading_none
54
+ product = products(:third_product)
55
+
56
+ products = Product.includes(:product_tariffs).where(:id => product.id).references(:product_tariffs)
57
+ assert_equal(1, products.length)
58
+ assert_equal(product, products.first)
59
+ assert_empty(products.first.product_tariffs)
60
+ end
61
+
62
+ def test_find_includes_tariffs
63
+ # Old style
64
+ tariffs = Tariff.includes(:product_tariffs)
65
+ assert_equal(3, tariffs.length)
66
+ assert_equal(3, tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length})
67
+
68
+ # New style
69
+ tariffs = Tariff.includes(:product_tariffs)
70
+ assert_equal(3, tariffs.length)
71
+ assert_equal(3, tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length})
72
+ end
73
+
74
+ def test_has_one_association_is_not_cached_to_where_it_returns_the_wrong_one
75
+ engineering = departments(:engineering)
76
+ engineering_head = engineering.head
77
+
78
+ accounting = departments(:accounting)
79
+ accounting_head = accounting.head
80
+
81
+ refute_equal accounting_head, engineering_head
82
+ end
83
+
84
+ def test_has_one_association_primary_key_and_foreign_key_are_present
85
+ steve = employees(:steve)
86
+ steve_salary = steve.create_one_salary(year: "2015", month: "1")
87
+
88
+ jill = employees(:jill)
89
+ jill_salary = jill.create_one_salary(year: "2015", month: "1")
90
+
91
+ steve_salary.reload
92
+ jill_salary.reload
93
+ assert_equal(steve.id, steve_salary.employee_id)
94
+ assert_equal(1, steve_salary.location_id)
95
+ assert_equal(jill.id, jill_salary.employee_id)
96
+ assert_equal(1, jill_salary.location_id)
97
+ end
98
+
99
+ def test_has_many_association_is_not_cached_to_where_it_returns_the_wrong_ones
100
+ engineering = departments(:engineering)
101
+ engineering_employees = engineering.employees
102
+
103
+ accounting = departments(:accounting)
104
+ accounting_employees = accounting.employees
105
+
106
+ refute_equal accounting_employees, engineering_employees
107
+ end
108
+
109
+ def test_has_many_association_primary_key_and_foreign_key_are_present
110
+ steve = employees(:steve)
111
+ steve_salary = steve.salaries.create(year: 2015, month: 1)
112
+
113
+ jill = employees(:jill)
114
+ jill_salary = jill.salaries.create(year: 2015, month: 1)
115
+
116
+ steve_salary.reload
117
+ jill_salary.reload
118
+ assert_equal(steve.id, steve_salary.employee_id)
119
+ assert_equal(1, steve_salary.location_id)
120
+ assert_equal(jill.id, jill_salary.employee_id)
121
+ assert_equal(1, jill_salary.location_id)
122
+ end
123
+
124
+ def test_belongs_to_association_primary_key_and_foreign_key_are_present
125
+ bogus_foreign_key = 2_500_000
126
+ salary_01 = Salary.new(
127
+ year: 2015,
128
+ month: 1,
129
+ employee_id: bogus_foreign_key,
130
+ location_id: 1
131
+ )
132
+ employee_01 = salary_01.create_employee
133
+ employee_01.reload
134
+
135
+ assert_equal(salary_01.employee_id, employee_01.id, "Generated id used")
136
+ assert_not_equal(bogus_foreign_key, employee_01.id, "Bogus value ignored")
137
+ assert_equal(1, employee_01.location_id)
138
+ end
139
+
140
+ def test_find_includes_product_tariffs_product
141
+ # Old style
142
+ product_tariffs = ProductTariff.includes(:product)
143
+ assert_not_nil(product_tariffs)
144
+ assert_equal(3, product_tariffs.length)
145
+
146
+ # New style
147
+ product_tariffs = ProductTariff.includes(:product)
148
+ assert_not_nil(product_tariffs)
149
+ assert_equal(3, product_tariffs.length)
150
+ end
151
+
152
+ def test_find_includes_product_tariffs_tariff
153
+ # Old style
154
+ product_tariffs = ProductTariff.includes(:tariff)
155
+ assert_equal(3, product_tariffs.length)
156
+
157
+ # New style
158
+ product_tariffs = ProductTariff.includes(:tariff)
159
+ assert_equal(3, product_tariffs.length)
160
+ end
161
+
162
+ def test_has_many_through
163
+ products = Product.includes(:tariffs)
164
+ assert_equal(3, products.length)
165
+
166
+ tarrifs_length = products.inject(0) {|sum, product| sum + product.tariffs.length}
167
+ assert_equal(3, tarrifs_length)
168
+ end
169
+
170
+ def test_new_style_includes_with_conditions
171
+ product_tariff = ProductTariff.includes(:tariff).where('tariffs.amount < 5').references(:tariffs).first
172
+ assert_equal(0, product_tariff.tariff.amount)
173
+ end
174
+
175
+ def test_find_product_includes
176
+ products = Product.includes(:product_tariffs => :tariff)
177
+ assert_equal(3, products.length)
178
+
179
+ product_tariffs_length = products.inject(0) {|sum, product| sum + product.product_tariffs.length}
180
+ assert_equal(3, product_tariffs_length)
181
+ end
182
+
183
+ def test_find_tariffs_includes
184
+ tariffs = Tariff.includes(:product_tariffs => :product)
185
+ assert_equal(3, tariffs.length)
186
+
187
+ product_tariffs_length = tariffs.inject(0) {|sum, tariff| sum + tariff.product_tariffs.length}
188
+ assert_equal(3, product_tariffs_length)
189
+ end
190
+
191
+ def test_has_many_through_when_not_pre_loaded
192
+ student = Student.first
193
+ rooms = student.rooms
194
+ assert_equal(1, rooms.size)
195
+ assert_equal(1, rooms.first.dorm_id)
196
+ assert_equal(1, rooms.first.room_id)
197
+ end
198
+
199
+ def test_has_many_through_when_through_association_is_composite
200
+ dorm = Dorm.first
201
+ assert_equal(3, dorm.rooms.length)
202
+ assert_equal(1, dorm.rooms.first.room_attributes.length)
203
+ assert_equal('type', dorm.rooms.first.room_attributes.first.name)
204
+ end
205
+
206
+ def test_associations_with_conditions
207
+ suburb = Suburb.find([2, 1])
208
+ assert_equal 2, suburb.streets.size
209
+
210
+ suburb = Suburb.find([2, 1])
211
+ assert_equal 1, suburb.first_streets.size
212
+
213
+ suburb = Suburb.includes(:streets).find([2, 1])
214
+ assert_equal 2, suburb.streets.size
215
+
216
+ suburb = Suburb.includes(:first_streets).find([2, 1])
217
+ assert_equal 1, suburb.first_streets.size
218
+ end
219
+
220
+ def test_composite_has_many_composites
221
+ room = rooms(:branner_room_1)
222
+ assert_equal(2, room.room_assignments.length)
223
+ assert_equal(room_assignments(:jacksons_room), room.room_assignments[0])
224
+ assert_equal(room_assignments(:bobs_room), room.room_assignments[1])
225
+ end
226
+
227
+ def test_composite_belongs_to_composite
228
+ room_assignment = room_assignments(:jacksons_room)
229
+ assert_equal(rooms(:branner_room_1), room_assignment.room)
230
+ end
231
+
232
+ def test_composite_belongs_to_changes
233
+ room_assignment = room_assignments(:jacksons_room)
234
+ room_assignment.room = rooms(:branner_room_2)
235
+ # This was raising an error before:
236
+ # TypeError: [:dorm_id, :room_id] is not a symbol
237
+ # changes returns HashWithIndifferentAccess
238
+ assert_equal({"room_id"=>[1, 2]}, room_assignment.changes)
239
+
240
+ steve = employees(:steve)
241
+ steve.department = departments(:engineering)
242
+ # It was returning this before:
243
+ # {"[:department_id, :location_id]"=>[nil, [2, 1]]}
244
+ assert_equal({"department_id"=>[1, 2]}, steve.changes)
245
+ end
246
+
247
+ def test_composite_belongs_to__setting_to_nil
248
+ room_assignment = room_assignments(:jacksons_room)
249
+ # This was raising an error before:
250
+ # NoMethodError: undefined method `length' for nil:NilClass
251
+ assert_nothing_raised { room_assignment.room = nil }
252
+ end
253
+
254
+ def test_has_one_with_composite
255
+ # In this case a regular model has_one composite model
256
+ department = departments(:engineering)
257
+ assert_not_nil(department.head)
258
+ end
259
+
260
+ def test_has_many_build__simple_key
261
+ user = users(:santiago)
262
+ reading = user.readings.build
263
+ assert_equal user.id, reading.user_id
264
+ assert_equal user, reading.user
265
+ end
266
+
267
+ def test_has_many_build__composite_key
268
+ department = departments(:engineering)
269
+ employee = department.employees.build
270
+ assert_equal department.department_id, employee.department_id
271
+ assert_equal department.location_id, employee.location_id
272
+ assert_equal department, employee.department
273
+ end
274
+
275
+ def test_has_many_with_primary_key
276
+ @membership = Membership.find([1, 1])
277
+ assert_equal 2, @membership.readings.size
278
+ end
279
+
280
+ def test_has_many_with_composite_key
281
+ # In this case a regular model (Dorm) has_many composite models (Rooms)
282
+ dorm = dorms(:branner)
283
+ assert_equal(3, dorm.rooms.length)
284
+ assert_equal(1, dorm.rooms[0].room_id)
285
+ assert_equal(2, dorm.rooms[1].room_id)
286
+ assert_equal(3, dorm.rooms[2].room_id)
287
+ end
288
+
289
+ def test_joins_has_many_with_primary_key
290
+ #@membership = Membership.find(:first, :joins => :readings, :conditions => { :readings => { :id => 1 } })
291
+ @membership = Membership.joins(:readings).where(readings: { id: 1 }).first
292
+
293
+ assert_equal [1, 1], @membership.id
294
+ end
295
+
296
+ def test_joins_has_one_with_primary_key
297
+ @membership = Membership.joins(:readings).where(readings: { id: 2 }).first
298
+
299
+ assert_equal [1, 1], @membership.id
300
+ end
301
+
302
+ def test_has_many_through_with_conditions_when_through_association_is_not_composite
303
+ user = User.first
304
+ assert_equal 1, user.articles.where("articles.name = ?", "Article One").size
305
+ end
306
+
307
+ def test_has_many_through_with_conditions_when_through_association_is_composite
308
+ room = Room.first
309
+ assert_equal 0, room.room_attributes.where("room_attributes.name != ?", "type").size
310
+ end
311
+
312
+ def test_has_many_through_on_custom_finder_when_through_association_is_composite_finder_when_through_association_is_not_composite
313
+ user = User.first
314
+ assert_equal(1, user.find_custom_articles.size)
315
+ end
316
+
317
+ def test_has_many_through_on_custom_finder_when_through_association_is_composite
318
+ room = Room.first
319
+ assert_equal(0, room.find_custom_room_attributes.size)
320
+ end
321
+
322
+ def test_has_many_with_primary_key_with_associations
323
+ memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses)
324
+ assert_equal(2, memberships.length)
325
+ assert_equal([1,1], memberships[0].id)
326
+ assert_equal([3,2], memberships[1].id)
327
+ end
328
+
329
+ def test_limitable_reflections
330
+ memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses).limit(1)
331
+ assert_equal(1, memberships.length)
332
+ assert_equal([1,1], memberships[0].id)
333
+ end
334
+
335
+ def test_foreign_key_present_with_null_association_ids
336
+ group = Group.new
337
+ group.memberships.build
338
+ associations = group.association_cache[:memberships]
339
+ assert_equal(false, associations.send('foreign_key_present?'))
340
+ end
341
+ end