composite_primary_keys 9.0.4 → 9.0.5

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +20 -0
  3. data/Rakefile +37 -34
  4. data/lib/composite_primary_keys.rb +5 -10
  5. data/lib/composite_primary_keys/arel/in.rb +6 -6
  6. data/lib/composite_primary_keys/arel/sqlserver.rb +36 -0
  7. data/lib/composite_primary_keys/associations/association_scope.rb +51 -29
  8. data/lib/composite_primary_keys/attribute_methods/read.rb +3 -1
  9. data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +22 -0
  10. data/lib/composite_primary_keys/relation.rb +30 -0
  11. data/lib/composite_primary_keys/relation/query_methods.rb +25 -36
  12. data/lib/composite_primary_keys/sanitization.rb +31 -47
  13. data/lib/composite_primary_keys/version.rb +1 -1
  14. data/tasks/databases/mysql.rake +40 -42
  15. data/tasks/databases/oracle.rake +29 -15
  16. data/tasks/databases/postgresql.rake +38 -47
  17. data/tasks/databases/sqlite.rake +25 -0
  18. data/tasks/databases/sqlserver.rake +32 -16
  19. data/test/abstract_unit.rb +12 -11
  20. data/test/connections/connection_spec.rb +27 -18
  21. data/test/connections/databases.ci.yml +5 -4
  22. data/test/connections/databases.example.yml +19 -4
  23. data/test/connections/databases.yml +25 -4
  24. data/test/fixtures/article.rb +6 -5
  25. data/test/fixtures/db_definitions/mysql.sql +16 -7
  26. data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
  27. data/test/fixtures/db_definitions/oracle.sql +25 -15
  28. data/test/fixtures/db_definitions/postgresql.sql +11 -2
  29. data/test/fixtures/db_definitions/sqlite.sql +8 -0
  30. data/test/fixtures/db_definitions/sqlserver.sql +19 -33
  31. data/test/fixtures/pk_called_id.rb +5 -0
  32. data/test/fixtures/pk_called_ids.yml +11 -0
  33. data/test/test_associations.rb +334 -332
  34. data/test/test_create.rb +9 -1
  35. data/test/test_delete.rb +17 -39
  36. data/test/test_ids.rb +113 -109
  37. data/test/test_preload.rb +94 -0
  38. data/test/test_suite.rb +1 -1
  39. data/test/test_update.rb +12 -7
  40. metadata +14 -24
  41. data/lib/composite_primary_keys/associations/singular_association.rb +0 -14
  42. data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +0 -71
  43. data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +0 -50
  44. data/lib/composite_primary_keys/dirty.rb +0 -19
  45. data/lib/composite_primary_keys/validations/uniqueness.rb +0 -41
  46. data/tasks/databases/oracle_enhanced.rake +0 -27
  47. data/tasks/databases/sqlite3.rake +0 -27
  48. data/test/connections/native_ibm_db/connection.rb +0 -19
  49. data/test/connections/native_mysql/connection.rb +0 -17
  50. data/test/connections/native_oracle/connection.rb +0 -11
  51. data/test/connections/native_oracle_enhanced/connection.rb +0 -16
  52. data/test/connections/native_postgresql/connection.rb +0 -13
  53. data/test/connections/native_sqlite3/connection.rb +0 -9
  54. data/test/connections/native_sqlserver/connection.rb +0 -11
  55. data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -92
  56. data/test/test_delete_all.rb +0 -29
@@ -1,7 +1,7 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestCreate < ActiveSupport::TestCase
4
- fixtures :students, :dorms, :rooms, :room_assignments, :reference_types, :reference_codes, :streets, :suburbs
4
+ fixtures :articles, :students, :dorms, :rooms, :room_assignments, :reference_types, :reference_codes, :streets, :suburbs
5
5
 
6
6
  CLASSES = {
7
7
  :single => {
@@ -153,4 +153,12 @@ class TestCreate < ActiveSupport::TestCase
153
153
  assert_equal(assignment1, room.room_assignments[0])
154
154
  assert_equal(assignment2, room.room_assignments[1])
155
155
  end
156
+
157
+ def test_create_article_invalid_id
158
+ error = assert_raises(ActiveRecord::RecordInvalid) do
159
+ article = Article.create!(:id => 1)
160
+ end
161
+
162
+ assert_equal('Validation failed: Id has already been taken', error.to_s)
163
+ end
156
164
  end
@@ -4,50 +4,28 @@ class TestDelete < ActiveSupport::TestCase
4
4
  fixtures :articles, :departments, :employees, :products, :tariffs, :product_tariffs,
5
5
  :reference_types, :reference_codes
6
6
 
7
- CLASSES = {
8
- :single => {
9
- :class => ReferenceType,
10
- :primary_keys => :reference_type_id,
11
- },
12
- :dual => {
13
- :class => ReferenceCode,
14
- :primary_keys => [:reference_type_id, :reference_code],
15
- },
16
- }
17
-
18
- def setup
19
- self.class.classes = CLASSES
20
- end
21
-
22
- def test_destroy_one
23
- testing_with do
24
- assert @first.destroy
25
- end
26
- end
27
-
28
- def test_destroy_one_alone_via_class
29
- testing_with do
30
- assert @klass.destroy(@first.id)
31
- end
7
+ def test_delete_one
8
+ assert_equal(5, ReferenceCode.count)
9
+ ReferenceCode.first.delete
10
+ assert_equal(4, ReferenceCode.count)
32
11
  end
33
12
 
34
- def test_delete_one_alone
35
- testing_with do
36
- assert @klass.delete(@first.id)
37
- end
13
+ def test_delete_one_with_id
14
+ assert_equal(5, ReferenceCode.count)
15
+ ReferenceCode.delete(ReferenceCode.first.id)
16
+ assert_equal(4, ReferenceCode.count)
38
17
  end
39
18
 
40
- def test_delete_many
41
- testing_with do
42
- to_delete = @klass.limit(2)
43
- assert_equal 2, to_delete.length
44
- end
19
+ def test_destroy_one
20
+ assert_equal(5, ReferenceCode.count)
21
+ ReferenceCode.first.destroy
22
+ assert_equal(4, ReferenceCode.count)
45
23
  end
46
24
 
47
25
  def test_delete_all
48
- testing_with do
49
- @klass.delete_all
50
- end
26
+ refute_empty(ReferenceCode.all)
27
+ ReferenceCode.delete_all
28
+ assert_empty(ReferenceCode.all)
51
29
  end
52
30
 
53
31
  def test_delete_all_with_join
@@ -56,8 +34,8 @@ class TestDelete < ActiveSupport::TestCase
56
34
  assert_equal(4, Department.count)
57
35
 
58
36
  Department.joins(:employees).
59
- where('departments.department_id = ?', department.department_id).
60
- where('departments.location_id = ?', department.location_id).
37
+ where('departments.department_id = ?', department.department_id).
38
+ where('departments.location_id = ?', department.location_id).
61
39
  delete_all
62
40
 
63
41
  assert_equal(3, Department.count)
@@ -1,109 +1,113 @@
1
- require File.expand_path('../abstract_unit', __FILE__)
2
-
3
- class ChildCpkTest < ReferenceCode
4
- end
5
-
6
- class TestIds < ActiveSupport::TestCase
7
- fixtures :reference_types, :reference_codes
8
-
9
- CLASSES = {
10
- :single => {
11
- :class => ReferenceType,
12
- :primary_keys => [:reference_type_id],
13
- },
14
- :dual => {
15
- :class => ReferenceCode,
16
- :primary_keys => [:reference_type_id, :reference_code],
17
- },
18
- :dual_strs => {
19
- :class => ReferenceCode,
20
- :primary_keys => ['reference_type_id', 'reference_code'],
21
- },
22
- }
23
-
24
- def setup
25
- self.class.classes = CLASSES
26
- end
27
-
28
- def test_id
29
- testing_with do
30
- assert_equal @first.id, @first.ids if composite?
31
- assert_kind_of(CompositePrimaryKeys::CompositeKeys, @first.id) if composite?
32
- end
33
- end
34
-
35
- def test_to_param
36
- testing_with do
37
- assert_equal '1,1', @first.to_param if composite?
38
- end
39
- end
40
-
41
- def test_ids_to_s
42
- testing_with do
43
- order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
44
- to_test = @klass.order(order)[0..1].map(&:id)
45
- assert_equal '(1,1),(1,2)', @klass.ids_to_s(to_test) if @key_test == :dual
46
- assert_equal '1,1;1,2', @klass.ids_to_s(to_test, ',', ';', '', '') if @key_test == :dual
47
- end
48
- end
49
-
50
- def test_set_ids_string
51
- testing_with do
52
- array = @primary_keys.collect {|key| 5}
53
- expected = composite? ? array.to_composite_keys : array.first
54
- @first.id = expected.to_s
55
- assert_equal expected, @first.id
56
- end
57
- end
58
-
59
- def test_set_ids_array
60
- testing_with do
61
- array = @primary_keys.collect {|key| 5}
62
- expected = composite? ? array.to_composite_keys : array.first
63
- @first.id = expected
64
- assert_equal expected, @first.id
65
- end
66
- end
67
-
68
- def test_set_ids_comp
69
- testing_with do
70
- array = @primary_keys.collect {|key| 5}
71
- expected = composite? ? array.to_composite_keys : array.first
72
- @first.id = expected
73
- assert_equal expected, @first.id
74
- end
75
- end
76
-
77
- def test_primary_keys
78
- testing_with do
79
- if composite?
80
- assert_not_nil @klass.primary_keys
81
- assert_equal @primary_keys.map {|key| key.to_s}, @klass.primary_keys
82
- assert_equal @klass.primary_keys, @klass.primary_key
83
- assert_kind_of(CompositePrimaryKeys::CompositeKeys, @klass.primary_keys)
84
- assert_equal @primary_keys.map {|key| key.to_sym}.join(','), @klass.primary_key.to_s
85
- else
86
- assert_not_nil @klass.primary_key
87
- assert_equal @primary_keys.first, @klass.primary_key.to_sym
88
- assert_equal @primary_keys.first.to_s, @klass.primary_key.to_s
89
- end
90
- end
91
- end
92
-
93
- def test_inherited_primary_keys
94
- assert_equal(["reference_type_id", "reference_code"], ChildCpkTest.primary_keys)
95
- end
96
-
97
- def test_inherited_ids
98
- cpk_test = ChildCpkTest.new
99
- assert_equal([nil, nil], cpk_test.id)
100
- end
101
-
102
- def test_assign_ids
103
- ref_code = ReferenceCode.new
104
- assert_equal([nil, nil], ref_code.id)
105
-
106
- ref_code.id = [2,1]
107
- assert_equal([2,1], ref_code.id)
108
- end
109
- end
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class ChildCpkTest < ReferenceCode
4
+ end
5
+
6
+ class TestIds < ActiveSupport::TestCase
7
+ fixtures :reference_types, :reference_codes, :pk_called_ids
8
+
9
+ CLASSES = {
10
+ :single => {
11
+ :class => ReferenceType,
12
+ :primary_keys => [:reference_type_id],
13
+ },
14
+ :dual => {
15
+ :class => ReferenceCode,
16
+ :primary_keys => [:reference_type_id, :reference_code],
17
+ },
18
+ :dual_strs => {
19
+ :class => ReferenceCode,
20
+ :primary_keys => ['reference_type_id', 'reference_code'],
21
+ },
22
+ :pk_called_id => {
23
+ :class => PkCalledId,
24
+ :primary_keys => ['id', 'reference_code'],
25
+ },
26
+ }
27
+
28
+ def setup
29
+ self.class.classes = CLASSES
30
+ end
31
+
32
+ def test_id
33
+ testing_with do
34
+ assert_equal @first.id, @first.ids if composite?
35
+ assert_kind_of(CompositePrimaryKeys::CompositeKeys, @first.id) if composite?
36
+ end
37
+ end
38
+
39
+ def test_to_param
40
+ testing_with do
41
+ assert_equal '1,1', @first.to_param if composite?
42
+ end
43
+ end
44
+
45
+ def test_ids_to_s
46
+ testing_with do
47
+ order = @klass.primary_key.is_a?(String) ? @klass.primary_key : @klass.primary_key.join(',')
48
+ to_test = @klass.order(order)[0..1].map(&:id)
49
+ assert_equal '(1,1),(1,2)', @klass.ids_to_s(to_test) if @key_test == :dual
50
+ assert_equal '1,1;1,2', @klass.ids_to_s(to_test, ',', ';', '', '') if @key_test == :dual
51
+ end
52
+ end
53
+
54
+ def test_set_ids_string
55
+ testing_with do
56
+ array = @primary_keys.collect {|key| 5}
57
+ expected = composite? ? array.to_composite_keys : array.first
58
+ @first.id = expected.to_s
59
+ assert_equal expected, @first.id
60
+ end
61
+ end
62
+
63
+ def test_set_ids_array
64
+ testing_with do
65
+ array = @primary_keys.collect {|key| 5}
66
+ expected = composite? ? array.to_composite_keys : array.first
67
+ @first.id = expected
68
+ assert_equal expected, @first.id
69
+ end
70
+ end
71
+
72
+ def test_set_ids_comp
73
+ testing_with do
74
+ array = @primary_keys.collect {|key| 5}
75
+ expected = composite? ? array.to_composite_keys : array.first
76
+ @first.id = expected
77
+ assert_equal expected, @first.id
78
+ end
79
+ end
80
+
81
+ def test_primary_keys
82
+ testing_with do
83
+ if composite?
84
+ assert_not_nil @klass.primary_keys
85
+ assert_equal @primary_keys.map {|key| key.to_s}, @klass.primary_keys
86
+ assert_equal @klass.primary_keys, @klass.primary_key
87
+ assert_kind_of(CompositePrimaryKeys::CompositeKeys, @klass.primary_keys)
88
+ assert_equal @primary_keys.map {|key| key.to_sym}.join(','), @klass.primary_key.to_s
89
+ else
90
+ assert_not_nil @klass.primary_key
91
+ assert_equal @primary_keys.first, @klass.primary_key.to_sym
92
+ assert_equal @primary_keys.first.to_s, @klass.primary_key.to_s
93
+ end
94
+ end
95
+ end
96
+
97
+ def test_inherited_primary_keys
98
+ assert_equal(["reference_type_id", "reference_code"], ChildCpkTest.primary_keys)
99
+ end
100
+
101
+ def test_inherited_ids
102
+ cpk_test = ChildCpkTest.new
103
+ assert_equal([nil, nil], cpk_test.id)
104
+ end
105
+
106
+ def test_assign_ids
107
+ ref_code = ReferenceCode.new
108
+ assert_equal([nil, nil], ref_code.id)
109
+
110
+ ref_code.id = [2,1]
111
+ assert_equal([2,1], ref_code.id)
112
+ end
113
+ end
@@ -0,0 +1,94 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestPreload < ActiveSupport::TestCase
4
+ fixtures :comments, :users, :employees, :groups
5
+
6
+ class UserForPreload < User
7
+ has_many :comments_with_include_condition, -> { where('person_type = ?', 'User')},
8
+ class_name: 'Comment', foreign_key: 'person_id', as: :person
9
+ has_many :comments_with_exclude_condition, -> { where('person_type <> ?', 'SomeType')},
10
+ class_name: 'Comment', foreign_key: 'person_id', as: :person
11
+ end
12
+
13
+ class EmployeeForPreload < Employee
14
+ # this is a rather random condition, which should not interfere with the normal test queries
15
+ has_and_belongs_to_many :groups_2, class_name: 'Group', foreign_key: 'employee_id', join_table: 'employees_groups'
16
+ end
17
+
18
+ def test_preload_of_polymorphic_association
19
+ comment = Comment.where(id: [1, 2, 3]).all
20
+ persons = comment.map(&:person)
21
+ persons.each do |person|
22
+ assert_kind_of(ActiveRecord::Base, person)
23
+ end
24
+
25
+ comment = Comment.where(id: [1, 2, 3]).preload(:person).all
26
+ persons = comment.map(&:person)
27
+ persons.each do |person|
28
+ assert_kind_of(ActiveRecord::Base, person)
29
+ end
30
+ end
31
+
32
+ def test_preload_for_conditioned_has_many_association
33
+ # has one comment
34
+ user1 = users(:santiago)
35
+ user2 = UserForPreload.create(name: 'TestPreload')
36
+ Comment.create(person: user2, person_type: 'User')
37
+ Comment.create(person: user2, person_type: 'User')
38
+
39
+ users = UserForPreload.where(id: [user1.id, user2.id]).all
40
+ assert_equal(1, users.first.comments_with_include_condition.size)
41
+ assert_equal(2, users.second.comments_with_include_condition.size)
42
+
43
+ users = UserForPreload.where(id: [user1.id, user2.id]).preload(:comments_with_include_condition).all
44
+ assert_equal(1, users.first.comments_with_include_condition.size)
45
+ assert_equal(2, users.second.comments_with_include_condition.size)
46
+
47
+ users = UserForPreload.where(id: [user1.id, user2.id]).all
48
+ assert_equal(1, users.first.comments_with_exclude_condition.size)
49
+ assert_equal(2, users.second.comments_with_exclude_condition.size)
50
+
51
+ users = UserForPreload.where(id: [user1.id, user2.id]).preload(:comments_with_exclude_condition).all
52
+ assert_equal(1, users.first.comments_with_exclude_condition.size)
53
+ assert_equal(2, users.second.comments_with_exclude_condition.size)
54
+ end
55
+
56
+ def test_preload_for_unconditioned_habtm_association
57
+ employee1 = employees(:steve)
58
+ employee2 = employees(:jill)
59
+ employee1.groups = [groups(:cpk)]
60
+ employee2.groups = [groups(:cpk), groups(:group2)]
61
+ employee1.save!; employee2.save!
62
+
63
+ employees = Employee.where(id: [1, 2]).all
64
+ assert_equal(1, employees.first.groups.size)
65
+ assert_equal(2, employees.second.groups.size)
66
+
67
+ employees = Employee.where(id: [1, 2]).preload(:groups).all
68
+ assert_equal(1, employees.first.groups.size)
69
+ assert_equal(2, employees.second.groups.size)
70
+ end
71
+
72
+ def test_preload_for_conditioned_habtm_association
73
+ employee1 = employees(:steve)
74
+ employee2 = employees(:jill)
75
+ employee1.groups = [groups(:cpk)]
76
+ employee2.groups = [groups(:cpk), groups(:group2)]
77
+ employee1.save!; employee2.save!
78
+
79
+ employees = EmployeeForPreload.where(id: [1, 2]).all.order(:id)
80
+
81
+ # Even without preload two errors: First Employee has Group 1 loaded twice,
82
+ # Second Employee has only Group 2 instead of Group 1&2
83
+ assert_equal(1, employees.first.groups.size)
84
+ assert_equal(1, employees.first.groups_2.size)
85
+ assert_equal(2, employees.second.groups.size)
86
+ assert_equal(2, employees.second.groups_2.size)
87
+
88
+ employees = EmployeeForPreload.where(id: [1, 2]).preload(:groups_2).all.order(:id)
89
+
90
+ # with preloading, the first assertion is valid, but the second only gets Group 2 instead of 1&2
91
+ assert_equal(1, employees.first.groups_2.size)
92
+ assert_equal(2, employees.second.groups_2.size)
93
+ end
94
+ end
@@ -8,7 +8,6 @@
8
8
  test_composite_arrays
9
9
  test_create
10
10
  test_delete
11
- test_delete_all
12
11
  test_dumpable
13
12
  test_dup
14
13
  test_enum
@@ -23,6 +22,7 @@
23
22
  test_pagination
24
23
  test_polymorphic
25
24
  test_predicates
25
+ test_preload
26
26
  test_santiago
27
27
  test_serialize
28
28
  test_touch
@@ -40,8 +40,6 @@ class TestUpdate < ActiveSupport::TestCase
40
40
  obj = ReferenceCode.find([1,1])
41
41
  obj.reference_type_id = 2
42
42
  obj.reference_code = 3
43
- assert(obj.primary_key_changed?)
44
- assert_equal({"reference_type_id" => 1, "reference_code" => 1}, obj.primary_key_was)
45
43
  assert_equal({"reference_type_id" => 2, "reference_code" => 3}, obj.ids_hash)
46
44
  assert(obj.save)
47
45
  assert(obj.reload)
@@ -61,11 +59,18 @@ class TestUpdate < ActiveSupport::TestCase
61
59
  end
62
60
 
63
61
  def test_update_all
64
- assert_nothing_raised do
65
- reference_code = ReferenceCode.create
66
- primary_key = reference_code.class.primary_key
67
- ReferenceCode.where(primary_key => reference_code[primary_key]).
68
- update_all(description: 'random value')
62
+ ReferenceCode.update_all(description: 'random value')
63
+
64
+ ReferenceCode.all.each do |reference_code|
65
+ assert_equal('random value', reference_code.description)
66
+ end
67
+ end
68
+
69
+ def test_update_all_join
70
+ ReferenceCode.joins(:reference_type).update_all(description: 'random value')
71
+
72
+ ReferenceCode.all.each do |reference_code|
73
+ assert_equal('random value', reference_code.description)
69
74
  end
70
75
  end
71
76
  end