composite_primary_keys 8.1.0 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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