composite_primary_keys 13.0.8 → 13.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8604d48445aede0e7f6d39ad32090ea2ed0f8d7cd58ab633a3d0c013ee1ab3b8
4
- data.tar.gz: a71f857e9125065b7c635170c341ce4a9285f6942c8989dac9cfa201f428a062
3
+ metadata.gz: 7a669eb0a0494f42052831fcbe76de73b149c431ab64e8544e4e16770629379f
4
+ data.tar.gz: 022bd9e17155073ee11a6f2a4fd082771a9bd58d3a58e53e73283b5b7d3c76f1
5
5
  SHA512:
6
- metadata.gz: fb13f66165419e9ca60e9b1b3283ff174947d3d2d07d1b7e29a62cb0feae97bbe5abc3179d41f330f76d2837d27c837875a01039f1c9e2969769293c4617b7d2
7
- data.tar.gz: 14790bef238c5f4e6360a5613db1bd22e3333bc06a062bc6047212b077d02828bb6d1acdda436f8a4106bc1e82dc6fe4ef96d2e05f5f3dd72beb86bf0c4ae0a1
6
+ metadata.gz: b437679d051728600686978837e23b0835031c3ad9702506d172636d3a47d06d2653d68e5c8fcb3934e50b87cb61b8df852be8039ce1a0dcd8aef1dee6cfae0b
7
+ data.tar.gz: 8ac2b3d595ee688434c9d0e38b262292f0fd6fa15854c6538e97d834bab0ae81e7edb1e3bfcaa12d1a63ae0dcc8d4d29bab6382fa762397522e4685f8a0ea194
data/History.rdoc CHANGED
@@ -1,3 +1,7 @@
1
+ == 13.0.8 (2024-12-19)
2
+ * Fix `update_all` to update loaded associations (Piotr Kowalski)
3
+ * Fix object comparison for models with composite keys (Piotr Kowalski)
4
+
1
5
  == 13.0.8 (2023-11-24)
2
6
  Fix `polymorphic_name` support (Vladimir Kochnev)
3
7
 
@@ -16,6 +16,29 @@ module ActiveRecord
16
16
  super
17
17
  end
18
18
 
19
+ def primary_key_values_present?
20
+ if self.composite?
21
+ id.all? {|key| !key.nil?}
22
+ else
23
+ !id.nil?
24
+ end
25
+ end
26
+
27
+ def ==(comparison_object)
28
+ super ||
29
+ comparison_object.instance_of?(self.class) &&
30
+ primary_key_values_present? &&
31
+ comparison_object.id == id
32
+ end
33
+
34
+ def hash
35
+ if primary_key_values_present?
36
+ self.class.hash ^ id.hash
37
+ else
38
+ super
39
+ end
40
+ end
41
+
19
42
  module ClassMethods
20
43
  def find(*ids) # :nodoc:
21
44
  # We don't have cache keys for this stuff yet
@@ -19,23 +19,22 @@ module ActiveRecord
19
19
  def update_all(updates)
20
20
  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
21
21
 
22
- if eager_loading?
23
- relation = apply_join_dependency
24
- return relation.update_all(updates)
25
- end
22
+ arel = eager_loading? ? apply_join_dependency.arel : build_arel
23
+ arel.source.left = table
26
24
 
27
25
  stmt = Arel::UpdateManager.new
28
- stmt.table(arel.join_sources.empty? ? table : arel.source)
26
+ stmt.table(arel.source)
29
27
  stmt.key = table[primary_key]
30
28
 
31
29
  # CPK
32
- if @klass.composite?
30
+ if klass.composite?
33
31
  stmt = Arel::UpdateManager.new
34
32
  stmt.table(arel_table)
35
33
  cpk_subquery(stmt)
36
34
  else
37
35
  stmt.wheres = arel.constraints
38
36
  end
37
+
39
38
  stmt.take(arel.limit)
40
39
  stmt.offset(arel.offset)
41
40
  stmt.order(*arel.orders)
@@ -52,7 +51,7 @@ module ActiveRecord
52
51
  stmt.set Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
53
52
  end
54
53
 
55
- @klass.connection.update stmt, "#{@klass} Update All"
54
+ klass.connection.update(stmt, "#{klass} Update All").tap { reset }
56
55
  end
57
56
 
58
57
  def delete_all
@@ -64,17 +63,15 @@ module ActiveRecord
64
63
  raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
65
64
  end
66
65
 
67
- if eager_loading?
68
- relation = apply_join_dependency
69
- return relation.delete_all
70
- end
66
+ arel = eager_loading? ? apply_join_dependency.arel : build_arel
67
+ arel.source.left = table
71
68
 
72
69
  stmt = Arel::DeleteManager.new
73
- stmt.from(arel.join_sources.empty? ? table : arel.source)
70
+ stmt.from(arel.source)
74
71
  stmt.key = table[primary_key]
75
72
 
76
73
  # CPK
77
- if @klass.composite?
74
+ if klass.composite?
78
75
  stmt = Arel::DeleteManager.new
79
76
  stmt.from(arel_table)
80
77
  cpk_subquery(stmt)
@@ -86,7 +83,7 @@ module ActiveRecord
86
83
  stmt.offset(arel.offset)
87
84
  stmt.order(*arel.orders)
88
85
 
89
- affected = @klass.connection.delete(stmt, "#{@klass} Destroy")
86
+ affected = klass.connection.delete(stmt, "#{klass} Destroy")
90
87
 
91
88
  reset
92
89
  affected
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION
3
3
  MAJOR = 13
4
4
  MINOR = 0
5
- TINY = 8
5
+ TINY = 9
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
data/test/test_equal.rb CHANGED
@@ -1,26 +1,55 @@
1
1
  require File.expand_path('../abstract_unit', __FILE__)
2
2
 
3
3
  class TestEqual < ActiveSupport::TestCase
4
- fixtures :capitols
4
+ fixtures :restaurants, :products
5
5
 
6
- def test_new
7
- assert_equal(Capitol.new, Capitol.new)
6
+ ############################################################
7
+ ### Tests for Product model with single primary key (id) ###
8
+ ############################################################
9
+
10
+ def test_single_same
11
+ first = Product.find(1)
12
+ second = Product.find(1)
13
+ assert_equal(first, second)
14
+ end
15
+
16
+ def test_different
17
+ first = Product.find(1)
18
+ second = Product.find(2)
19
+ assert_not_equal(first, second)
20
+ end
21
+
22
+ def test_two_new_objects_are_not_equal
23
+ assert_not_equal(Product.new, Product.new)
8
24
  end
9
25
 
10
- def test_same_new
11
- it = Capitol.new
26
+ def test_same_new_object_is_equal_to_itself
27
+ it = Product.new
12
28
  assert_equal(it, it)
13
29
  end
14
30
 
15
- def test_same
16
- first = Capitol.find(['Canada', 'Ottawa'])
17
- second = Capitol.find(['Canada', 'Ottawa'])
31
+ #####################################################################################
32
+ ### Tests for Restaurant model with composite primary key (franchise_id, store_id) ##
33
+ #####################################################################################
34
+
35
+ def test_composite_same
36
+ first = Restaurant.find([1, 1])
37
+ second = Restaurant.find([1, 1])
18
38
  assert_equal(first, second)
19
39
  end
20
40
 
21
- def test_different
22
- first = Capitol.find(['Mexico', 'Mexico City'])
23
- second = Capitol.find(['Canada', 'Ottawa'])
41
+ def test_composite_different
42
+ first = Restaurant.find([1, 1])
43
+ second = Restaurant.find([2, 2])
24
44
  assert_not_equal(first, second)
25
45
  end
46
+
47
+ def test_composite_two_new_objects_are_not_equal
48
+ assert_not_equal(Restaurant.new, Restaurant.new)
49
+ end
50
+
51
+ def test_composite_same_new_object_is_equal_to_itself
52
+ it = Restaurant.new
53
+ assert_equal(it, it)
54
+ end
26
55
  end
data/test/test_hash.rb ADDED
@@ -0,0 +1,73 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestHash < ActiveSupport::TestCase
4
+ fixtures :restaurants, :products
5
+
6
+ ############################################################
7
+ ### Tests for Product model with single primary key (id) ###
8
+ ############################################################
9
+
10
+ def test_single_same_object_has_the_same_hash
11
+ first = Product.find(1)
12
+ second = Product.find(1)
13
+ assert_equal(first.hash, second.hash)
14
+ end
15
+
16
+ def test_single_different_objects_have_different_hashes
17
+ first = Product.find(1)
18
+ second = Product.find(2)
19
+ assert_not_equal(first.hash, second.hash)
20
+ end
21
+
22
+ def test_single_persisted_object_hash_is_based_on_primary_key
23
+ first = Product.find(1)
24
+ second = Product.find(1)
25
+
26
+ assert_equal(first.hash, second.hash)
27
+ first.name = 'new name'
28
+ assert_equal(first.hash, second.hash)
29
+ end
30
+
31
+ def test_single_two_new_objects_have_different_hashes
32
+ assert_not_equal(Product.new.hash, Product.new.hash)
33
+ end
34
+
35
+ def test_single_same_new_object_has_the_same_hash
36
+ it = Product.new
37
+ assert_equal(it.hash, it.hash)
38
+ end
39
+
40
+ #####################################################################################
41
+ ### Tests for Restaurant model with composite primary key (franchise_id, store_id) ##
42
+ #####################################################################################
43
+
44
+ def test_composite_same_object_has_the_same_hash
45
+ first = Restaurant.find([1, 1])
46
+ second = Restaurant.find([1, 1])
47
+ assert_equal(first.hash, second.hash)
48
+ end
49
+
50
+ def test_composite_different_objects_have_different_hashes
51
+ first = Restaurant.find([1, 1])
52
+ second = Restaurant.find([2, 2])
53
+ assert_not_equal(first.hash, second.hash)
54
+ end
55
+
56
+ def test_composite_persisted_object_hash_is_based_on_primary_key
57
+ first = Restaurant.find([1, 1])
58
+ second = Restaurant.find([1, 1])
59
+
60
+ assert_equal(first.hash, second.hash)
61
+ first.name = 'new name'
62
+ assert_equal(first.hash, second.hash)
63
+ end
64
+
65
+ def test_composite_two_new_objects_have_different_hashes
66
+ assert_not_equal(Restaurant.new.hash, Restaurant.new.hash)
67
+ end
68
+
69
+ def test_composite_same_new_object_has_the_same_hash
70
+ it = Restaurant.new
71
+ assert_equal(it.hash, it.hash)
72
+ end
73
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestRelation < ActiveSupport::TestCase
4
+ fixtures :users, :readings
5
+
6
+ def test_update_all_updates_db_records
7
+ user = User.find(1)
8
+ assert_equal [4, 5], user.readings.map(&:rating)
9
+
10
+ user.readings.update_all(rating: 3)
11
+
12
+ # Reload to check that the records were updated in the DB
13
+ user.readings.reload
14
+ assert_equal [3, 3], user.readings.map(&:rating)
15
+ end
16
+
17
+ def test_update_all_updates_loaded_association
18
+ user = User.find(1)
19
+ assert_equal [4, 5], user.readings.map(&:rating)
20
+
21
+ user.readings.update_all(rating: 3)
22
+
23
+ # No reload to check that not only the records were updated in the DB
24
+ # but also in the loaded association
25
+ assert_equal [3, 3], user.readings.map(&:rating)
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composite_primary_keys
3
3
  version: !ruby/object:Gem::Version
4
- version: 13.0.8
4
+ version: 13.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charlie Savage
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-11-24 00:00:00.000000000 Z
10
+ date: 2024-12-19 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -39,7 +38,6 @@ dependencies:
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
40
  description: Composite key support for ActiveRecord
42
- email:
43
41
  executables: []
44
42
  extensions: []
45
43
  extra_rdoc_files: []
@@ -184,6 +182,7 @@ files:
184
182
  - test/test_exists.rb
185
183
  - test/test_find.rb
186
184
  - test/test_habtm.rb
185
+ - test/test_hash.rb
187
186
  - test/test_ids.rb
188
187
  - test/test_miscellaneous.rb
189
188
  - test/test_nested_attributes.rb
@@ -192,6 +191,7 @@ files:
192
191
  - test/test_polymorphic.rb
193
192
  - test/test_predicates.rb
194
193
  - test/test_preload.rb
194
+ - test/test_relation.rb
195
195
  - test/test_santiago.rb
196
196
  - test/test_serialize.rb
197
197
  - test/test_touch.rb
@@ -202,7 +202,6 @@ homepage: https://github.com/composite-primary-keys/composite_primary_keys
202
202
  licenses:
203
203
  - MIT
204
204
  metadata: {}
205
- post_install_message:
206
205
  rdoc_options: []
207
206
  require_paths:
208
207
  - lib
@@ -217,8 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
216
  - !ruby/object:Gem::Version
218
217
  version: '0'
219
218
  requirements: []
220
- rubygems_version: 3.4.21
221
- signing_key:
219
+ rubygems_version: 3.6.1
222
220
  specification_version: 4
223
221
  summary: Composite key support for ActiveRecord
224
222
  test_files:
@@ -239,6 +237,7 @@ test_files:
239
237
  - test/test_exists.rb
240
238
  - test/test_find.rb
241
239
  - test/test_habtm.rb
240
+ - test/test_hash.rb
242
241
  - test/test_ids.rb
243
242
  - test/test_miscellaneous.rb
244
243
  - test/test_nested_attributes.rb
@@ -247,6 +246,7 @@ test_files:
247
246
  - test/test_polymorphic.rb
248
247
  - test/test_predicates.rb
249
248
  - test/test_preload.rb
249
+ - test/test_relation.rb
250
250
  - test/test_santiago.rb
251
251
  - test/test_serialize.rb
252
252
  - test/test_touch.rb