composite_primary_keys 12.0.0 → 12.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +44 -3
  3. data/README.rdoc +3 -2
  4. data/lib/composite_primary_keys.rb +57 -57
  5. data/lib/composite_primary_keys/active_model/attribute_assignment.rb +19 -0
  6. data/lib/composite_primary_keys/arel/sqlserver.rb +1 -3
  7. data/lib/composite_primary_keys/associations/through_association.rb +2 -1
  8. data/lib/composite_primary_keys/attribute_methods.rb +2 -2
  9. data/lib/composite_primary_keys/attribute_methods/primary_key.rb +13 -0
  10. data/lib/composite_primary_keys/base.rb +12 -1
  11. data/lib/composite_primary_keys/composite_arrays.rb +49 -14
  12. data/lib/composite_primary_keys/connection_adapters/abstract/database_statements.rb +8 -3
  13. data/lib/composite_primary_keys/connection_adapters/abstract_adapter.rb +1 -1
  14. data/lib/composite_primary_keys/connection_adapters/mysql/database_statements.rb +24 -0
  15. data/lib/composite_primary_keys/connection_adapters/sqlserver/database_statements.rb +33 -12
  16. data/lib/composite_primary_keys/core.rb +1 -1
  17. data/lib/composite_primary_keys/persistence.rb +2 -2
  18. data/lib/composite_primary_keys/relation.rb +100 -25
  19. data/lib/composite_primary_keys/relation/finder_methods.rb +6 -6
  20. data/lib/composite_primary_keys/relation/predicate_builder/association_query_value.rb +1 -1
  21. data/lib/composite_primary_keys/validations/uniqueness.rb +1 -1
  22. data/lib/composite_primary_keys/version.rb +1 -1
  23. data/test/abstract_unit.rb +3 -5
  24. data/test/fixtures/article.rb +4 -0
  25. data/test/fixtures/articles.yml +4 -3
  26. data/test/fixtures/comment.rb +1 -3
  27. data/test/fixtures/comments.yml +10 -9
  28. data/test/fixtures/db_definitions/db2-create-tables.sql +0 -14
  29. data/test/fixtures/db_definitions/db2-drop-tables.sql +1 -3
  30. data/test/fixtures/db_definitions/mysql.sql +7 -44
  31. data/test/fixtures/db_definitions/oracle.drop.sql +3 -9
  32. data/test/fixtures/db_definitions/oracle.sql +12 -48
  33. data/test/fixtures/db_definitions/postgresql.sql +7 -44
  34. data/test/fixtures/db_definitions/sqlite.sql +6 -42
  35. data/test/fixtures/db_definitions/sqlserver.sql +5 -41
  36. data/test/fixtures/department.rb +8 -3
  37. data/test/fixtures/departments.yml +4 -4
  38. data/test/fixtures/readings.yml +2 -2
  39. data/test/fixtures/restaurants_suburbs.yml +1 -1
  40. data/test/fixtures/streets.yml +2 -2
  41. data/test/fixtures/suburbs.yml +2 -2
  42. data/test/fixtures/user.rb +3 -2
  43. data/test/test_associations.rb +30 -23
  44. data/test/test_composite_arrays.rb +14 -0
  45. data/test/test_create.rb +15 -18
  46. data/test/test_delete.rb +3 -3
  47. data/test/test_exists.rb +5 -5
  48. data/test/test_find.rb +22 -2
  49. data/test/test_habtm.rb +2 -2
  50. data/test/test_ids.rb +5 -6
  51. data/test/test_nested_attributes.rb +0 -57
  52. data/test/test_polymorphic.rb +29 -13
  53. data/test/test_preload.rb +4 -3
  54. data/test/test_serialize.rb +2 -2
  55. data/test/test_update.rb +19 -1
  56. metadata +6 -64
  57. data/test/fixtures/hack.rb +0 -5
  58. data/test/fixtures/hacks.yml +0 -3
  59. data/test/fixtures/pk_called_id.rb +0 -5
  60. data/test/fixtures/pk_called_ids.yml +0 -11
  61. data/test/fixtures/reference_code_using_composite_key_alias.rb +0 -8
  62. data/test/fixtures/reference_code_using_simple_key_alias.rb +0 -8
  63. data/test/fixtures/seat.rb +0 -5
  64. data/test/fixtures/seats.yml +0 -9
  65. data/test/fixtures/topic.rb +0 -6
  66. data/test/fixtures/topic_source.rb +0 -7
  67. data/test/mkmf.log +0 -592
  68. data/test/test_aliases.rb +0 -18
  69. data/test/test_enum.rb +0 -21
  70. data/test/test_suite.rb +0 -35
@@ -1,9 +1,10 @@
1
1
  class User < ActiveRecord::Base
2
2
  has_many :readings
3
3
  has_many :articles, :through => :readings
4
+
4
5
  has_many :comments, :as => :person
5
- has_many :hacks, :through => :comments, :source => :hack
6
-
6
+ has_one :first_comment, :as => :person, :class_name => "Comment"
7
+
7
8
  def find_custom_articles
8
9
  articles.where("name = ?", "Article One")
9
10
  end
@@ -96,18 +96,23 @@ class TestAssociations < ActiveSupport::TestCase
96
96
  end
97
97
 
98
98
  def test_has_one_association_primary_key_and_foreign_key_are_present
99
- department = departments(:human_resources)
99
+ # department = departments(:engineering)
100
+ # assert_equal(2, department.employees.count)
101
+ # assert_equal('Sarah', department.employees[0].name)
102
+ # assert_equal('Robert', department.employees[1].name)
103
+ # assert_equal('Sarah', department.head.name)
100
104
 
105
+ department = departments(:human_resources)
101
106
  assert_equal(1, department.employees.count)
102
107
  assert_equal('Mindy', department.employees[0].name)
108
+ assert_equal('Mindy', department.head.name)
103
109
 
104
110
  head = department.create_head(name: 'Rick')
105
- assert_equal(department.department_id, head.department_id)
106
- assert_equal(department.location_id, head.location_id)
111
+ assert_equal(department, head.department)
112
+ assert_equal('Rick', department.head.name)
107
113
 
108
114
  department.reload
109
115
  assert_equal(1, department.employees.count)
110
- assert_equal('Rick', department.employees[0].name)
111
116
  end
112
117
 
113
118
  def test_has_one_autosave
@@ -139,9 +144,10 @@ class TestAssociations < ActiveSupport::TestCase
139
144
 
140
145
  department.reload
141
146
  assert_equal(3, department.employees.count)
142
- assert_equal('Steve', department.employees[0].name)
143
- assert_equal('Jill', department.employees[1].name)
144
- assert_equal('Rick', department.employees[2].name)
147
+ employees = department.employees.sort_by(&:name)
148
+ assert_equal('Jill', employees[0].name)
149
+ assert_equal('Rick', employees[1].name)
150
+ assert_equal('Steve', employees[2].name)
145
151
  end
146
152
 
147
153
  def test_find_includes_product_tariffs_product
@@ -174,6 +180,13 @@ class TestAssociations < ActiveSupport::TestCase
174
180
  assert_equal(3, tarrifs_length)
175
181
  end
176
182
 
183
+ def test_has_many_through_2
184
+ assert_equal(3, Article.count)
185
+ user = users(:santiago)
186
+ article_names = user.articles.map(&:name).sort
187
+ assert_equal(['Article One', 'Article Two'], article_names)
188
+ end
189
+
177
190
  def test_new_style_includes_with_conditions
178
191
  product_tariff = ProductTariff.includes(:tariff).where('tariffs.amount < 5').references(:tariffs).first
179
192
  assert_equal(0, product_tariff.tariff.amount)
@@ -203,16 +216,8 @@ class TestAssociations < ActiveSupport::TestCase
203
216
  end
204
217
 
205
218
  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])
219
+ suburb = Suburb.find([2, 2])
213
220
  assert_equal 2, suburb.streets.size
214
-
215
- suburb = Suburb.includes(:first_streets).find([2, 1])
216
221
  assert_equal 1, suburb.first_streets.size
217
222
  end
218
223
 
@@ -239,7 +244,7 @@ class TestAssociations < ActiveSupport::TestCase
239
244
  steve = employees(:steve)
240
245
  steve.department = departments(:engineering)
241
246
  # It was returning this before:
242
- # {"[:department_id, :location_id]"=>[nil, [2, 1]]}
247
+ # {"[:id, :location_id]"=>[nil, [2, 1]]}
243
248
  assert_equal({"department_id"=>[1, 2]}, steve.changes)
244
249
  end
245
250
 
@@ -263,12 +268,12 @@ class TestAssociations < ActiveSupport::TestCase
263
268
  assert_equal user, reading.user
264
269
  end
265
270
 
266
- def test_has_many_build__composite_key
271
+ def test_has_many_build_composite_key
267
272
  department = departments(:engineering)
268
273
  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
274
+ assert_equal(department[:id], employee.department_id)
275
+ assert_equal(department.location_id, employee.location_id)
276
+ assert_equal(department, employee.department)
272
277
  end
273
278
 
274
279
  def test_has_many_with_primary_key
@@ -331,9 +336,11 @@ class TestAssociations < ActiveSupport::TestCase
331
336
  end
332
337
 
333
338
  def test_limitable_reflections
334
- memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses).limit(1)
335
- assert_equal(1, memberships.length)
339
+ memberships = Membership.includes(:statuses).where("membership_statuses.status = ?", 'Active').references(:membership_statuses)
340
+ assert_equal(2, memberships.length)
341
+
336
342
  assert_equal([1,1], memberships[0].id)
343
+ assert_equal([3,2], memberships[1].id)
337
344
  end
338
345
 
339
346
  def test_foreign_key_present_with_null_association_ids
@@ -21,4 +21,18 @@ class CompositeArraysTest < ActiveSupport::TestCase
21
21
  assert_equal CompositePrimaryKeys::CompositeKeys, keys.class
22
22
  assert_equal '1,2,3', keys.to_s
23
23
  end
24
+
25
+ def test_parse
26
+ assert_equal ['1', '2'], CompositePrimaryKeys::CompositeKeys.parse('1,2')
27
+ assert_equal ['The USA', '^Washington, D.C.'],
28
+ CompositePrimaryKeys::CompositeKeys.parse('The USA,^5EWashington^2C D.C.')
29
+ assert_equal ['The USA', '^Washington, D.C.'],
30
+ CompositePrimaryKeys::CompositeKeys.parse(['The USA', '^Washington, D.C.'])
31
+ end
32
+
33
+ def test_to_s
34
+ assert_equal '1,2', CompositePrimaryKeys::CompositeKeys.new([1, 2]).to_s
35
+ assert_equal 'The USA,^5EWashington^2C D.C.',
36
+ CompositePrimaryKeys::CompositeKeys.new(['The USA', '^Washington, D.C.']).to_s
37
+ end
24
38
  end
@@ -48,16 +48,21 @@ class TestCreate < ActiveSupport::TestCase
48
48
  end
49
49
  end
50
50
 
51
- # def test_create_generated_keys
52
- # # Not all databases support columns with multiple identity fields
53
- # if defined?(ActiveRecord::ConnectionAdapters::PostgreSQL) ||
54
- # defined?(ActiveRecord::ConnectionAdapters::SQLite3)
55
- #
56
- # suburb = Suburb.create!(:name => 'Capitol Hill')
57
- # refute_nil(suburb.city_id)
58
- # refute_nil(suburb.suburb_id)
59
- # end
60
- # end
51
+ def test_create_with_partial_serial
52
+ attributes = {:location_id => 100}
53
+
54
+ # SQLite does not support an autoincrementing field in a composite key
55
+ if Department.connection.class.name == "ActiveRecord::ConnectionAdapters::SQLite3Adapter"
56
+ attributes[:id] = 100
57
+ end
58
+
59
+ department = Department.new(attributes)
60
+ assert_nil(department.attributes[:id])
61
+
62
+ department.save!
63
+ refute_nil(department.attributes["id"])
64
+ assert_equal(100, department.location_id)
65
+ end
61
66
 
62
67
  def test_create_on_association
63
68
  suburb = Suburb.first
@@ -165,14 +170,6 @@ class TestCreate < ActiveSupport::TestCase
165
170
  assert_equal(assignment2, room.room_assignments[1])
166
171
  end
167
172
 
168
- def test_create_article_invalid_id
169
- error = assert_raises(ActiveRecord::RecordInvalid) do
170
- Article.create!(:id => 1)
171
- end
172
-
173
- assert_equal('Validation failed: Id has already been taken', error.to_s)
174
- end
175
-
176
173
  def test_find_or_create_by
177
174
  suburb = Suburb.find_by(:city_id => 3, :suburb_id => 1)
178
175
  assert_nil(suburb)
@@ -131,13 +131,13 @@ class TestDelete < ActiveSupport::TestCase
131
131
  def test_delete_not_destroy_on_cpk
132
132
  tariff = Tariff.where(tariff_id: 2).first
133
133
  tariff.delete
134
- assert !tariff.persisted?
134
+ refute(tariff.persisted?)
135
135
  end
136
136
 
137
137
  def test_delete_not_destroy_on_non_cpk
138
- article = Article.first
138
+ article = articles(:third)
139
139
  article.delete
140
- assert !article.persisted?
140
+ refute(article.persisted?)
141
141
  end
142
142
 
143
143
  def test_destroy_has_many_delete_all
@@ -1,11 +1,11 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestExists < ActiveSupport::TestCase
4
- fixtures :articles, :departments, :capitols
4
+ fixtures :articles, :capitols, :departments, :dorms
5
5
 
6
6
  def test_id
7
- assert(Article.exists?(1))
8
- assert(!Article.exists?(-1))
7
+ assert(Dorm.exists?(1))
8
+ refute(Dorm.exists?(-1))
9
9
  end
10
10
 
11
11
  def test_array
@@ -29,8 +29,8 @@ class TestExists < ActiveSupport::TestCase
29
29
  end
30
30
 
31
31
  def test_cpk_array_condition
32
- assert(Department.exists?(['department_id = ? and location_id = ?', 1, 1]))
33
- assert(!Department.exists?(['department_id = ? and location_id = ?', 1, -1]))
32
+ assert(Department.exists?(['id = ? and location_id = ?', 1, 1]))
33
+ assert(!Department.exists?(['id = ? and location_id = ?', 1, -1]))
34
34
  end
35
35
 
36
36
  def test_cpk_array_string_id
@@ -41,6 +41,14 @@ class TestFind < ActiveSupport::TestCase
41
41
  assert_equal(['The Netherlands', 'Amsterdam'], capitol.id)
42
42
  end
43
43
 
44
+ def test_find_with_strings_with_comma_as_composite_keys
45
+ capitol = Capitol.create!(country: 'The USA', city: 'Washington, D.C.')
46
+ assert_equal ['The USA', 'Washington, D.C.'], capitol.id
47
+
48
+ assert_equal capitol, Capitol.find(['The USA', 'Washington, D.C.'])
49
+ assert_equal capitol, Capitol.find(capitol.to_param)
50
+ end
51
+
44
52
  def test_find_each
45
53
  room_assignments = []
46
54
  RoomAssignment.find_each(:batch_size => 2) do |assignment|
@@ -51,7 +59,7 @@ class TestFind < ActiveSupport::TestCase
51
59
  end
52
60
 
53
61
  def test_find_each_with_scope
54
- scoped_departments = Department.where("department_id <> 3")
62
+ scoped_departments = Department.where("id <> 3")
55
63
  scoped_departments.find_each(:batch_size => 2) do |department|
56
64
  assert department.id != 3
57
65
  end
@@ -66,9 +74,21 @@ class TestFind < ActiveSupport::TestCase
66
74
  assert_equal(with_quoted_identifiers(expected), error.message)
67
75
  end
68
76
 
77
+ def test_find_with_invalid_ids
78
+ assert_raise(::ActiveRecord::RecordNotFound) do
79
+ Suburb.find([-1, -1])
80
+ end
81
+ end
82
+
83
+ def test_find_with_no_ids
84
+ assert_raise(::ActiveRecord::RecordNotFound) do
85
+ Suburb.find
86
+ end
87
+ end
88
+
69
89
  def test_find_last_suburb
70
90
  suburb = Suburb.last
71
- assert_equal([2,1], suburb.id)
91
+ assert_equal([2,2], suburb.id)
72
92
  end
73
93
 
74
94
  def test_find_last_suburb_with_order
@@ -133,9 +133,9 @@ class TestHabtm < ActiveSupport::TestCase
133
133
 
134
134
  # reload to force reload of associations
135
135
  product_one = Product.find(1)
136
- assert_equal 2, product_one.restaurants.size
136
+ assert_equal(2, product_one.restaurants.size)
137
137
 
138
138
  product_three = Product.find(3)
139
- assert_equal 0, product_three.restaurants.size
139
+ assert_equal(0, product_three.restaurants.size)
140
140
  end
141
141
  end
@@ -4,7 +4,7 @@ class ChildCpkTest < ReferenceCode
4
4
  end
5
5
 
6
6
  class TestIds < ActiveSupport::TestCase
7
- fixtures :reference_types, :reference_codes, :pk_called_ids
7
+ fixtures :reference_types, :reference_codes
8
8
 
9
9
  CLASSES = {
10
10
  :single => {
@@ -18,11 +18,7 @@ class TestIds < ActiveSupport::TestCase
18
18
  :dual_strs => {
19
19
  :class => ReferenceCode,
20
20
  :primary_keys => ['reference_type_id', 'reference_code'],
21
- },
22
- :pk_called_id => {
23
- :class => PkCalledId,
24
- :primary_keys => ['id', 'reference_code'],
25
- },
21
+ }
26
22
  }
27
23
 
28
24
  def setup
@@ -40,6 +36,9 @@ class TestIds < ActiveSupport::TestCase
40
36
  testing_with do
41
37
  assert_equal '1,1', @first.to_param if composite?
42
38
  end
39
+
40
+ capitol = Capitol.create!(country: 'The USA', city: 'Washington, D.C.')
41
+ assert_equal 'The USA,Washington^2C D.C.', capitol.to_param
43
42
  end
44
43
 
45
44
  def test_ids_to_s
@@ -64,61 +64,4 @@ class TestNestedAttributes < ActiveSupport::TestCase
64
64
  assert_equal(reference_code.code_label, 'XX')
65
65
  assert_equal(reference_code.abbreviation, 'Xx')
66
66
  end
67
-
68
- fixtures :topics, :topic_sources
69
-
70
- def test_nested_attributes_create_with_string_in_primary_key
71
- platform = 'instagram'
72
-
73
- topic = topics(:music)
74
- topic.update :topic_sources_attributes => [{
75
- :platform => platform,
76
- :keywords => 'funk'
77
- }]
78
- assert_not_nil TopicSource.find_by_platform(platform)
79
- end
80
-
81
- def test_nested_attributes_update_with_string_in_primary_key
82
- platform = 'instagram'
83
-
84
- topic = topics(:music)
85
- topic.update :topic_sources_attributes => [{
86
- :platform => platform,
87
- :keywords => 'funk'
88
- }]
89
- assert_not_nil TopicSource.find_by_platform(platform)
90
-
91
- topic_source = TopicSource.find_by_platform(platform)
92
- cpk = CompositePrimaryKeys::CompositeKeys[topic.id, platform]
93
- topic.update :topic_sources_attributes => [{
94
- :id => cpk,
95
- :keywords => 'jazz'
96
- }]
97
-
98
- topic_source = TopicSource.find_by_platform(platform)
99
- assert_kind_of(TopicSource, topic_source)
100
- assert_equal(topic_source.keywords, 'jazz')
101
- end
102
-
103
- def test_nested_attributes_update_with_string_in_primary_key_2
104
- topic = topics(:music)
105
- topic_source = topic_sources(:music_source)
106
-
107
- topic.update(:topic_sources_attributes => [{:id => topic_source.id,
108
- :keywords => 'classical, jazz'}])
109
-
110
- topic_source.reload
111
- assert_equal(topic_source.keywords, 'classical, jazz')
112
- end
113
-
114
- def test_nested_attributes_update_with_string_in_primary_key_3
115
- topic = topics(:music)
116
- topic_source = topic_sources(:music_source)
117
-
118
- topic.update(:topic_sources_attributes => [{:id => topic_source.id.to_s,
119
- :keywords => 'classical, jazz'}])
120
-
121
- topic_source.reload
122
- assert_equal(topic_source.keywords, 'classical, jazz')
123
- end
124
67
  end
@@ -1,27 +1,43 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestPolymorphic < ActiveSupport::TestCase
4
- fixtures :users, :employees, :comments, :hacks, :articles, :readings
4
+ fixtures :articles, :departments, :employees, :users, :comments
5
5
 
6
- def test_polymorphic_has_many
7
- comments = Hack.find(7).comments
8
- assert_equal 7, comments[0].person_id
6
+ def test_has_many
7
+ user = users(:santiago)
8
+ comments = user.comments
9
+ assert_equal(user.id, comments[0].person_id)
9
10
  end
10
11
 
11
- def test_polymorphic_has_one
12
- first_comment = Hack.find(7).first_comment
13
- assert_equal 7, first_comment.person_id
12
+ def test_has_one
13
+ user = users(:santiago)
14
+ first_comment = user.first_comment
15
+ assert_equal(user.id, first_comment.person_id)
14
16
  end
15
17
 
16
18
  def test_has_many_through
17
- assert_equal(2, Article.count, 'Baseline sanity check')
18
- user = users(:santiago)
19
- article_names = user.articles.collect { |a| a.name }.sort
20
- assert_equal ['Article One', 'Article Two'], article_names
19
+ department = departments(:accounting)
20
+ comment = comments(:employee_comment)
21
+
22
+ assert_equal(1, department.comments.size)
23
+ assert_equal(comment, department.comments[0])
21
24
  end
22
25
 
23
- def test_polymorphic_has_many_through
26
+ def test_has_many_through_2
27
+ article = articles(:second)
28
+
24
29
  user = users(:santiago)
25
- assert_equal(['andrew'], user.hacks.collect { |a| a.name }.sort)
30
+ assert_equal(user, article.user_commentators[0])
31
+
32
+ user = users(:drnic)
33
+ assert_equal(user, article.user_commentators[1])
34
+ end
35
+
36
+ def test_clear_has_many_through
37
+ article = articles(:second)
38
+
39
+ assert_equal(2, article.comments.size)
40
+ article.user_commentators = []
41
+ assert_equal(0, article.comments.size)
26
42
  end
27
43
  end
@@ -1,7 +1,7 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestPreload < ActiveSupport::TestCase
4
- fixtures :comments, :users, :employees, :groups, :hacks, :readings
4
+ fixtures :articles, :comments, :users, :employees, :groups, :readings
5
5
 
6
6
  class UserForPreload < User
7
7
  has_many :comments_with_include_condition, -> { where('person_type = ?', 'User')},
@@ -31,10 +31,11 @@ class TestPreload < ActiveSupport::TestCase
31
31
 
32
32
  def test_preload_for_conditioned_has_many_association
33
33
  # has one comment
34
+ article = articles(:first)
34
35
  user1 = users(:santiago)
35
36
  user2 = UserForPreload.create(name: 'TestPreload')
36
- Comment.create(person: user2, person_type: 'User')
37
- Comment.create(person: user2, person_type: 'User')
37
+ Comment.create(article: article, person: user2, person_type: 'User')
38
+ Comment.create(article: article, person: user2, person_type: 'User')
38
39
 
39
40
  users = UserForPreload.where(id: [user1.id, user2.id]).all
40
41
  assert_equal(1, users.first.comments_with_include_condition.size)