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.
- checksums.yaml +4 -4
- data/History.rdoc +20 -0
- data/Rakefile +37 -34
- data/lib/composite_primary_keys.rb +5 -10
- data/lib/composite_primary_keys/arel/in.rb +6 -6
- data/lib/composite_primary_keys/arel/sqlserver.rb +36 -0
- data/lib/composite_primary_keys/associations/association_scope.rb +51 -29
- data/lib/composite_primary_keys/attribute_methods/read.rb +3 -1
- data/lib/composite_primary_keys/connection_adapters/abstract_mysql_adapter.rb +22 -0
- data/lib/composite_primary_keys/relation.rb +30 -0
- data/lib/composite_primary_keys/relation/query_methods.rb +25 -36
- data/lib/composite_primary_keys/sanitization.rb +31 -47
- data/lib/composite_primary_keys/version.rb +1 -1
- data/tasks/databases/mysql.rake +40 -42
- data/tasks/databases/oracle.rake +29 -15
- data/tasks/databases/postgresql.rake +38 -47
- data/tasks/databases/sqlite.rake +25 -0
- data/tasks/databases/sqlserver.rake +32 -16
- data/test/abstract_unit.rb +12 -11
- data/test/connections/connection_spec.rb +27 -18
- data/test/connections/databases.ci.yml +5 -4
- data/test/connections/databases.example.yml +19 -4
- data/test/connections/databases.yml +25 -4
- data/test/fixtures/article.rb +6 -5
- data/test/fixtures/db_definitions/mysql.sql +16 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle.sql +25 -15
- data/test/fixtures/db_definitions/postgresql.sql +11 -2
- data/test/fixtures/db_definitions/sqlite.sql +8 -0
- data/test/fixtures/db_definitions/sqlserver.sql +19 -33
- data/test/fixtures/pk_called_id.rb +5 -0
- data/test/fixtures/pk_called_ids.yml +11 -0
- data/test/test_associations.rb +334 -332
- data/test/test_create.rb +9 -1
- data/test/test_delete.rb +17 -39
- data/test/test_ids.rb +113 -109
- data/test/test_preload.rb +94 -0
- data/test/test_suite.rb +1 -1
- data/test/test_update.rb +12 -7
- metadata +14 -24
- data/lib/composite_primary_keys/associations/singular_association.rb +0 -14
- data/lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb +0 -71
- data/lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb +0 -50
- data/lib/composite_primary_keys/dirty.rb +0 -19
- data/lib/composite_primary_keys/validations/uniqueness.rb +0 -41
- data/tasks/databases/oracle_enhanced.rake +0 -27
- data/tasks/databases/sqlite3.rake +0 -27
- data/test/connections/native_ibm_db/connection.rb +0 -19
- data/test/connections/native_mysql/connection.rb +0 -17
- data/test/connections/native_oracle/connection.rb +0 -11
- data/test/connections/native_oracle_enhanced/connection.rb +0 -16
- data/test/connections/native_postgresql/connection.rb +0 -13
- data/test/connections/native_sqlite3/connection.rb +0 -9
- data/test/connections/native_sqlserver/connection.rb +0 -11
- data/test/fixtures/db_definitions/sqlserver.drop.sql +0 -92
- data/test/test_delete_all.rb +0 -29
data/test/test_create.rb
CHANGED
@@ -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
|
data/test/test_delete.rb
CHANGED
@@ -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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
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 = ?',
|
60
|
-
where('departments.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)
|
data/test/test_ids.rb
CHANGED
@@ -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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
assert_equal @primary_keys.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
data/test/test_suite.rb
CHANGED
@@ -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
|
data/test/test_update.rb
CHANGED
@@ -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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|