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,28 +1,33 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class EmployeesGroup < ActiveRecord::Base
4
-
5
- end
6
-
7
- class TestValidations < ActiveSupport::TestCase
8
- fixtures :employees
9
-
10
- def test_delete_for_model_without_primary_key
11
- EmployeesGroup.create(employee_id: 1, group_id: 100)
12
- EmployeesGroup.create(employee_id: 2, group_id: 102)
13
- EmployeesGroup.create(employee_id: 3, group_id: 103)
14
-
15
- assert_equal(EmployeesGroup.all.size, 3)
16
- exception = assert_raises(ActiveRecord::StatementInvalid) {
17
- EmployeesGroup.where(employee_id: 1).first.destroy
18
- }
19
-
20
- mysql_match = /Unknown column 'employees_groups.' in 'where clause/ =~ exception.message
21
- sqlite3_match = /no such column: employees_groups./ =~ exception.message
22
- postgresql_match = /PG::SyntaxError: ERROR: zero-length delimited identifier/ =~ exception.message
23
-
24
- assert(postgresql_match || mysql_match || sqlite3_match)
25
-
26
- assert(EmployeesGroup.all.size == 3)
27
- end
28
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class EmployeesGroup < ActiveRecord::Base
4
+
5
+ end
6
+
7
+ class TestValidations < ActiveSupport::TestCase
8
+ fixtures :employees
9
+
10
+ def test_delete_for_model_without_primary_key
11
+ EmployeesGroup.create(employee_id: 1, group_id: 100)
12
+ EmployeesGroup.create(employee_id: 2, group_id: 102)
13
+ EmployeesGroup.create(employee_id: 3, group_id: 103)
14
+
15
+ assert_equal(EmployeesGroup.all.size, 3)
16
+ exception = assert_raises(ActiveRecord::StatementInvalid) {
17
+ EmployeesGroup.where(employee_id: 1).first.destroy
18
+ }
19
+
20
+ mysql_match = /Unknown column 'employees_groups.' in 'where clause/ =~ exception.message
21
+ sqlite3_match = /no such column: employees_groups./ =~ exception.message
22
+ postgresql_match = /PG::SyntaxError: ERROR: zero-length delimited identifier/ =~ exception.message
23
+
24
+ assert(postgresql_match || mysql_match || sqlite3_match)
25
+
26
+ assert(EmployeesGroup.all.size == 3)
27
+ end
28
+
29
+ # This test fails, requires fixin arel
30
+ #def test_delete_all_with_joins
31
+ # ReferenceCode.joins(:reference_type).where(:reference_type_id => 1).delete_all
32
+ #end
33
+ end
@@ -1,21 +1,21 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class TestEnum < ActiveSupport::TestCase
4
- fixtures :comments
5
-
6
- def test_enum_was
7
- comment = Comment.first
8
- assert_nil comment.shown
9
- puts "comment.changed_attributes = #{comment.changed_attributes.inspect}"
10
- comment.shown = :true
11
- puts "comment.changed_attributes = #{comment.changed_attributes.inspect}"
12
- assert_equal 'true', comment.shown
13
- assert_nil comment.shown_was
14
-
15
- comment.save
16
-
17
- comment.shown = :false
18
- assert_equal 'false', comment.shown
19
- assert_equal 'true', comment.shown_was
20
- end
21
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestEnum < ActiveSupport::TestCase
4
+ fixtures :comments
5
+
6
+ def test_enum_was
7
+ comment = Comment.first
8
+ assert_nil comment.shown
9
+ assert_equal({}, comment.changed_attributes)
10
+ comment.shown = :true
11
+ assert_equal({ "shown" => nil }, comment.changed_attributes)
12
+ assert_equal 'true', comment.shown
13
+ assert_nil comment.shown_was
14
+
15
+ comment.save
16
+
17
+ comment.shown = :false
18
+ assert_equal 'false', comment.shown
19
+ assert_equal 'true', comment.shown_was
20
+ end
21
+ end
@@ -1,26 +1,26 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class TestEqual < ActiveSupport::TestCase
4
- fixtures :capitols
5
-
6
- def test_new
7
- assert_not_equal(Capitol.new, Capitol.new)
8
- end
9
-
10
- def test_same_new
11
- it = Capitol.new
12
- assert_equal(it, it)
13
- end
14
-
15
- def test_same
16
- first = Capitol.find(['Canada', 'Ottawa'])
17
- second = Capitol.find(['Canada', 'Ottawa'])
18
- assert_equal(first, second)
19
- end
20
-
21
- def test_different
22
- first = Capitol.find(['Mexico', 'Mexico City'])
23
- second = Capitol.find(['Canada', 'Ottawa'])
24
- assert_not_equal(first, second)
25
- end
26
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestEqual < ActiveSupport::TestCase
4
+ fixtures :capitols
5
+
6
+ def test_new
7
+ assert_equal(Capitol.new, Capitol.new)
8
+ end
9
+
10
+ def test_same_new
11
+ it = Capitol.new
12
+ assert_equal(it, it)
13
+ end
14
+
15
+ def test_same
16
+ first = Capitol.find(['Canada', 'Ottawa'])
17
+ second = Capitol.find(['Canada', 'Ottawa'])
18
+ assert_equal(first, second)
19
+ end
20
+
21
+ def test_different
22
+ first = Capitol.find(['Mexico', 'Mexico City'])
23
+ second = Capitol.find(['Canada', 'Ottawa'])
24
+ assert_not_equal(first, second)
25
+ end
26
+ end
@@ -1,118 +1,119 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- # Testing the find action on composite ActiveRecords with two primary keys
4
- class TestFind < ActiveSupport::TestCase
5
- fixtures :capitols, :departments, :reference_types, :reference_codes, :suburbs
6
-
7
- def test_find_first
8
- ref_code = ReferenceCode.order('reference_type_id, reference_code').first
9
- assert_kind_of(ReferenceCode, ref_code)
10
- assert_equal([1,1], ref_code.id)
11
- end
12
-
13
- def test_find_last
14
- ref_code = ReferenceCode.order('reference_type_id, reference_code').last
15
- assert_kind_of(ReferenceCode, ref_code)
16
- assert_equal([2,2], ref_code.id)
17
- end
18
-
19
- def test_find_one
20
- ref_code = ReferenceCode.find([1,3])
21
- assert_not_nil(ref_code)
22
- assert_equal([1,3], ref_code.id)
23
- end
24
-
25
- def test_find_some
26
- ref_codes = ReferenceCode.find([1,3], [2,1])
27
- assert_kind_of(Array, ref_codes)
28
- assert_equal(2, ref_codes.length)
29
-
30
- ref_code = ref_codes[0]
31
- assert_equal([1,3], ref_code.id)
32
-
33
- ref_code = ref_codes[1]
34
- assert_equal([2,1], ref_code.id)
35
- end
36
-
37
- def test_find_with_strings_as_composite_keys
38
- capitol = Capitol.find(['The Netherlands', 'Amsterdam'])
39
- assert_kind_of(Capitol, capitol)
40
- assert_equal(['The Netherlands', 'Amsterdam'], capitol.id)
41
- end
42
-
43
- def test_find_each
44
- room_assignments = []
45
- RoomAssignment.find_each(:batch_size => 2) do |assignment|
46
- room_assignments << assignment
47
- end
48
-
49
- assert_equal(RoomAssignment.count, room_assignments.uniq.length)
50
- end
51
-
52
- def test_find_each_with_scope
53
- scoped_departments = Department.where("department_id <> 3")
54
- scoped_departments.find_each(:batch_size => 2) do |department|
55
- assert department.id != 3
56
- end
57
- end
58
-
59
- def test_not_found
60
- error = assert_raise(::ActiveRecord::RecordNotFound) do
61
- ReferenceCode.find(['999', '999'])
62
- end
63
-
64
- connection = ActiveRecord::Base.connection
65
- ref_type_quoted = "#{connection.quote_table_name('reference_codes')}.#{connection.quote_column_name('reference_type_id')}"
66
- ref_code_quoted = "#{connection.quote_table_name('reference_codes')}.#{connection.quote_column_name('reference_code')}"
67
-
68
- expected = "Couldn't find all ReferenceCodes with 'reference_type_id,reference_code': (999, 999) (found 0 results, but was looking for 1)"
69
- assert_equal(with_quoted_identifiers(expected), error.message)
70
- end
71
-
72
- def test_find_last_suburb
73
- suburb = Suburb.last
74
- assert_equal([2,1], suburb.id)
75
- end
76
-
77
- def test_find_last_suburb_with_order
78
- # Rails actually changes city_id DESC to city_id ASC
79
- suburb = Suburb.order('suburbs.city_id DESC').last
80
- assert_equal([1,1], suburb.id)
81
- end
82
-
83
- def test_find_in_batches
84
- Department.find_in_batches do |batch|
85
- assert_equal(Department.count, batch.size)
86
- end
87
- end
88
-
89
- def test_expand
90
- department = departments(:engineering)
91
- employees = Employee.where(:department => department)
92
- assert_equal(2, employees.count)
93
- end
94
-
95
- def test_find_one_with_params_id
96
- params_id = ReferenceCode.find([1,3]).to_param
97
- assert_equal params_id, "1,3"
98
-
99
- ref_code = ReferenceCode.find(params_id)
100
- assert_not_nil(ref_code)
101
- assert_equal([1,3], ref_code.id)
102
- end
103
-
104
- def test_find_some_with_array_of_params_id
105
- params_ids = ReferenceCode.find([1,3], [2,1]).map(&:to_param)
106
- assert_equal ["1,3", "2,1"], params_ids
107
-
108
- ref_codes = ReferenceCode.find(params_ids)
109
- assert_kind_of(Array, ref_codes)
110
- assert_equal(2, ref_codes.length)
111
-
112
- ref_code = ref_codes[0]
113
- assert_equal([1,3], ref_code.id)
114
-
115
- ref_code = ref_codes[1]
116
- assert_equal([2,1], ref_code.id)
117
- end
118
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ # Testing the find action on composite ActiveRecords with two primary keys
4
+ class TestFind < ActiveSupport::TestCase
5
+ fixtures :capitols, :departments, :reference_types, :reference_codes,
6
+ :suburbs, :employees
7
+
8
+ def test_find_first
9
+ ref_code = ReferenceCode.order('reference_type_id, reference_code').first
10
+ assert_kind_of(ReferenceCode, ref_code)
11
+ assert_equal([1,1], ref_code.id)
12
+ end
13
+
14
+ def test_find_last
15
+ ref_code = ReferenceCode.order('reference_type_id, reference_code').last
16
+ assert_kind_of(ReferenceCode, ref_code)
17
+ assert_equal([2,2], ref_code.id)
18
+ end
19
+
20
+ def test_find_one
21
+ ref_code = ReferenceCode.find([1,3])
22
+ assert_not_nil(ref_code)
23
+ assert_equal([1,3], ref_code.id)
24
+ end
25
+
26
+ def test_find_some
27
+ ref_codes = ReferenceCode.find([1,3], [2,1])
28
+ assert_kind_of(Array, ref_codes)
29
+ assert_equal(2, ref_codes.length)
30
+
31
+ ref_code = ref_codes[0]
32
+ assert_equal([1,3], ref_code.id)
33
+
34
+ ref_code = ref_codes[1]
35
+ assert_equal([2,1], ref_code.id)
36
+ end
37
+
38
+ def test_find_with_strings_as_composite_keys
39
+ capitol = Capitol.find(['The Netherlands', 'Amsterdam'])
40
+ assert_kind_of(Capitol, capitol)
41
+ assert_equal(['The Netherlands', 'Amsterdam'], capitol.id)
42
+ end
43
+
44
+ def test_find_each
45
+ room_assignments = []
46
+ RoomAssignment.find_each(:batch_size => 2) do |assignment|
47
+ room_assignments << assignment
48
+ end
49
+
50
+ assert_equal(RoomAssignment.count, room_assignments.uniq.length)
51
+ end
52
+
53
+ def test_find_each_with_scope
54
+ scoped_departments = Department.where("department_id <> 3")
55
+ scoped_departments.find_each(:batch_size => 2) do |department|
56
+ assert department.id != 3
57
+ end
58
+ end
59
+
60
+ def test_not_found
61
+ error = assert_raise(::ActiveRecord::RecordNotFound) do
62
+ ReferenceCode.find(['999', '999'])
63
+ end
64
+
65
+ connection = ActiveRecord::Base.connection
66
+ ref_type_quoted = "#{connection.quote_table_name('reference_codes')}.#{connection.quote_column_name('reference_type_id')}"
67
+ ref_code_quoted = "#{connection.quote_table_name('reference_codes')}.#{connection.quote_column_name('reference_code')}"
68
+
69
+ expected = "Couldn't find all ReferenceCodes with 'reference_type_id,reference_code': (999, 999) (found 0 results, but was looking for 1)"
70
+ assert_equal(with_quoted_identifiers(expected), error.message)
71
+ end
72
+
73
+ def test_find_last_suburb
74
+ suburb = Suburb.last
75
+ assert_equal([2,1], suburb.id)
76
+ end
77
+
78
+ def test_find_last_suburb_with_order
79
+ # Rails actually changes city_id DESC to city_id ASC
80
+ suburb = Suburb.order('suburbs.city_id DESC').last
81
+ assert_equal([1,1], suburb.id)
82
+ end
83
+
84
+ def test_find_in_batches
85
+ Department.find_in_batches do |batch|
86
+ assert_equal(Department.count, batch.size)
87
+ end
88
+ end
89
+
90
+ def test_expand
91
+ department = departments(:engineering)
92
+ employees = Employee.where(:department => department)
93
+ assert_equal(2, employees.count)
94
+ end
95
+
96
+ def test_find_one_with_params_id
97
+ params_id = ReferenceCode.find([1,3]).to_param
98
+ assert_equal params_id, "1,3"
99
+
100
+ ref_code = ReferenceCode.find(params_id)
101
+ assert_not_nil(ref_code)
102
+ assert_equal([1,3], ref_code.id)
103
+ end
104
+
105
+ def test_find_some_with_array_of_params_id
106
+ params_ids = ReferenceCode.find([1,3], [2,1]).map(&:to_param)
107
+ assert_equal ["1,3", "2,1"], params_ids
108
+
109
+ ref_codes = ReferenceCode.find(params_ids)
110
+ assert_kind_of(Array, ref_codes)
111
+ assert_equal(2, ref_codes.length)
112
+
113
+ ref_code = ref_codes[0]
114
+ assert_equal([1,3], ref_code.id)
115
+
116
+ ref_code = ref_codes[1]
117
+ assert_equal([2,1], ref_code.id)
118
+ end
119
+ end
@@ -1,113 +1,117 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class TestHabtm < ActiveSupport::TestCase
4
- fixtures :suburbs, :restaurants, :restaurants_suburbs, :products
5
-
6
- def test_has_and_belongs_to_many
7
- @restaurant = Restaurant.find([1,1])
8
- assert_equal 2, @restaurant.suburbs.size
9
-
10
- @restaurant = Restaurant.includes(:suburbs).find([1,1])
11
- assert_equal 2, @restaurant.suburbs.size
12
- end
13
-
14
- def test_include_cpk_both_sides
15
- # assuming the association was set up in the fixtures
16
- # file restaurants_suburbs.yml
17
- mcdonalds = restaurants(:mcdonalds)
18
- # check positive
19
- suburb = mcdonalds.suburbs[0]
20
- assert mcdonalds.suburbs.include?(suburb)
21
- # check negative
22
- suburb_with_no_mcdonalds = suburbs(:no_mcdonalds)
23
- assert !mcdonalds.suburbs.include?(suburb_with_no_mcdonalds)
24
- end
25
-
26
- def test_include_cpk_owner_side_only
27
- subway = restaurants(:subway_one)
28
- product = products(:first_product)
29
- subway.products << product
30
-
31
- # reload
32
- # test positive
33
- subway = restaurants(:subway_one)
34
- assert subway.products.include?(product)
35
-
36
- # test negative
37
- product_two = products(:second_product)
38
- assert !subway.products.include?(product_two)
39
- end
40
-
41
- def test_include_cpk_association_side_only
42
- product = products(:first_product)
43
- subway = restaurants(:subway_one)
44
- product.restaurants << subway
45
-
46
- # reload
47
- # test positive
48
- product = products(:first_product)
49
- assert product.restaurants.include?(subway)
50
-
51
- # test negative
52
- mcdonalds = restaurants(:mcdonalds)
53
- assert !product.restaurants.include?(mcdonalds)
54
- end
55
-
56
- def test_habtm_clear_cpk_both_sides
57
- @restaurant = restaurants(:mcdonalds)
58
- assert_equal 2, @restaurant.suburbs.size
59
- @restaurant.suburbs.clear
60
- assert_equal 0, @restaurant.suburbs.size
61
- end
62
-
63
- def test_habtm_clear_cpk_owner_side_only
64
- subway = restaurants(:subway_one)
65
- first_product = products(:first_product)
66
- second_product = products(:second_product)
67
- subway.products << first_product << second_product
68
- assert_equal 2, subway.products.size
69
- subway.products.clear
70
- # reload to force reload of associations
71
- subway = restaurants(:subway_one)
72
- assert_equal 0, subway.products.size
73
- end
74
-
75
- def test_habtm_clear_cpk_association_side_only
76
- product = products(:first_product)
77
- subway_one = restaurants(:subway_one)
78
- subway_two = restaurants(:subway_two)
79
- product.restaurants << subway_one << subway_two
80
- assert_equal 2, product.restaurants.size
81
- product.restaurants.clear
82
- # reload to force reload of associations
83
- product = products(:first_product)
84
- assert_equal 0, product.restaurants.size
85
- end
86
-
87
- # tests case reported in issue #39 where a bug resulted in
88
- # deletion of incorrect join table records because the owner's id
89
- # was assumed to be an array and is not in this case
90
- # and evaluates to a useable but incorrect value
91
- def test_habtm_clear_cpk_association_side_only_deletes_only_correct_records
92
- product_one = Product.find(1)
93
- product_three = Product.find(3)
94
- subway_one = restaurants(:subway_one)
95
- subway_two = restaurants(:subway_two)
96
- product_one.restaurants << subway_one << subway_two
97
- product_three.restaurants << subway_one << subway_two
98
- assert_equal 2, product_one.restaurants.size
99
- assert_equal 2, product_three.restaurants.size
100
-
101
- # if product_three's id is incorrectly assumed to be
102
- # an array it will be evaluated as 3[0], which is 1, which would
103
- # delete product_one's associations rather than product_three's
104
- product_three.restaurants.clear
105
-
106
- # reload to force reload of associations
107
- product_one = Product.find(1)
108
- assert_equal 2, product_one.restaurants.size
109
-
110
- product_three = Product.find(3)
111
- assert_equal 0, product_three.restaurants.size
112
- end
113
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestHabtm < ActiveSupport::TestCase
4
+ fixtures :suburbs, :restaurants, :restaurants_suburbs, :products
5
+
6
+ def test_has_and_belongs_to_many
7
+ @restaurant = Restaurant.find([1,1])
8
+ assert_equal 2, @restaurant.suburbs.size
9
+
10
+ @restaurant = Restaurant.includes(:suburbs).find([1,1])
11
+ assert_equal 2, @restaurant.suburbs.size
12
+ end
13
+
14
+ def test_include_cpk_both_sides
15
+ # assuming the association was set up in the fixtures
16
+ # file restaurants_suburbs.yml
17
+ mcdonalds = restaurants(:mcdonalds)
18
+ # check positive
19
+ suburb = mcdonalds.suburbs[0]
20
+ assert mcdonalds.suburbs.include?(suburb)
21
+ # check negative
22
+ suburb_with_no_mcdonalds = suburbs(:no_mcdonalds)
23
+ assert !mcdonalds.suburbs.include?(suburb_with_no_mcdonalds)
24
+ end
25
+
26
+ def test_include_cpk_owner_side_only
27
+ subway = restaurants(:subway_one)
28
+ product = products(:first_product)
29
+ subway.products << product
30
+
31
+ # reload
32
+ # test positive
33
+ subway = restaurants(:subway_one)
34
+ assert subway.products.include?(product)
35
+
36
+ # test negative
37
+ product_two = products(:second_product)
38
+ assert !subway.products.include?(product_two)
39
+ end
40
+
41
+ def test_include_cpk_association_side_only
42
+ product = products(:first_product)
43
+ subway = restaurants(:subway_one)
44
+ product.restaurants << subway
45
+
46
+ # reload
47
+ # test positive
48
+ product = products(:first_product)
49
+ assert product.restaurants.include?(subway)
50
+
51
+ # test negative
52
+ mcdonalds = restaurants(:mcdonalds)
53
+ assert !product.restaurants.include?(mcdonalds)
54
+ end
55
+
56
+ def test_habtm_clear_cpk_both_sides
57
+ @restaurant = restaurants(:mcdonalds)
58
+ assert_equal 2, @restaurant.suburbs.size
59
+ @restaurant.suburbs.clear
60
+ assert_equal 0, @restaurant.suburbs.size
61
+ end
62
+
63
+ def test_habtm_clear_cpk_owner_side_only
64
+ subway = restaurants(:subway_one)
65
+ assert_equal 0, subway.products.size, 'Baseline'
66
+
67
+ first_product = products(:first_product)
68
+ second_product = products(:second_product)
69
+ subway.products << first_product << second_product
70
+ assert_equal 2, subway.products.size
71
+ subway.products.clear
72
+ # reload to force reload of associations
73
+ subway = restaurants(:subway_one)
74
+ assert_equal 0, subway.products.size
75
+ end
76
+
77
+ def test_habtm_clear_cpk_association_side_only
78
+ product = products(:first_product)
79
+ assert_equal 0, product.restaurants.size, 'Baseline'
80
+
81
+ subway_one = restaurants(:subway_one)
82
+ subway_two = restaurants(:subway_two)
83
+ product.restaurants << subway_one << subway_two
84
+ assert_equal 2, product.restaurants.size
85
+ product.restaurants.clear
86
+ # reload to force reload of associations
87
+ product = products(:first_product)
88
+ assert_equal 0, product.restaurants.size
89
+ end
90
+
91
+ # tests case reported in issue #39 where a bug resulted in
92
+ # deletion of incorrect join table records because the owner's id
93
+ # was assumed to be an array and is not in this case
94
+ # and evaluates to a useable but incorrect value
95
+ def test_habtm_clear_cpk_association_side_only_deletes_only_correct_records
96
+ product_one = Product.find(1)
97
+ product_three = Product.find(3)
98
+ subway_one = restaurants(:subway_one)
99
+ subway_two = restaurants(:subway_two)
100
+ product_one.restaurants << subway_one << subway_two
101
+ product_three.restaurants << subway_one << subway_two
102
+ assert_equal 2, product_one.restaurants.size
103
+ assert_equal 2, product_three.restaurants.size
104
+
105
+ # if product_three's id is incorrectly assumed to be
106
+ # an array it will be evaluated as 3[0], which is 1, which would
107
+ # delete product_one's associations rather than product_three's
108
+ product_three.restaurants.clear
109
+
110
+ # reload to force reload of associations
111
+ product_one = Product.find(1)
112
+ assert_equal 2, product_one.restaurants.size
113
+
114
+ product_three = Product.find(3)
115
+ assert_equal 0, product_three.restaurants.size
116
+ end
117
+ end