activerecord 7.0.5 → 7.0.6

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: f3039efb205667bcd9fc218b22042ee4a8f36b735f62fedf208a56b70bb3bd5c
4
- data.tar.gz: df54f94c2480c583f2236f31de29f55525ee8f281fea93b30690f57f775d758b
3
+ metadata.gz: 1fc8d9f64d2ef73d31d77f9bb3ab1792606a33e541bd28a08566304fc81d5d07
4
+ data.tar.gz: 7e4b61e90c14d831d3b888859ba713dd5cbb35d1554225aec1c483ee8857aee9
5
5
  SHA512:
6
- metadata.gz: a412b99cef7bb68b569f14be355f715f888f0072f33436d40ffe8e4c90c088539d0fd1d26d43e508d5e6a2089ad7a73874f1aef7094bc7dc5287bccca753496b
7
- data.tar.gz: 4b6008f67510a941efad31e7cddc4f6af2a7149da4a68cb248ce5481631c674216204d0a0028686c36a8f61f4366b1b2c096c5a6fd8ea61d29884bc57822a0fe
6
+ metadata.gz: faf9806425e9a75ecde61e1b84bc6eec459cd18895684200701394315b5e7bff69487a4baab67482a80baa1f5e2fcf81021781ceb81cba39f7fbc75bfe7200d4
7
+ data.tar.gz: b940c37c5f10f000f37ba68eb9be3aa2ae5dabc329a16979587dd1cd75ba464976cefccc437ba9958eb444a35f9303214d7e5f0d06d37b4e45809337977d8829
data/CHANGELOG.md CHANGED
@@ -1,3 +1,58 @@
1
+ ## Rails 7.0.6 (June 29, 2023) ##
2
+
3
+ * Fix autosave associations with validations added on `:base` of the associated objects.
4
+
5
+ *fatkodima*
6
+
7
+ * Fix result with anonymous PostgreSQL columns of different type from json.
8
+
9
+ *Oleksandr Avoiants*
10
+
11
+ * Preserve timestamp when setting an `ActiveSupport::TimeWithZone` value to `timestamptz` attribute.
12
+
13
+ *fatkodima*
14
+
15
+ * Fix where on association with has_one/has_many polymorphic relations.
16
+
17
+ Before:
18
+ ```ruby
19
+ Treasure.where(price_estimates: PriceEstimate.all)
20
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates")
21
+ ```
22
+
23
+ Later:
24
+ ```ruby
25
+ Treasure.where(price_estimates: PriceEstimate.all)
26
+ #=> SELECT (...) WHERE "treasures"."id" IN (SELECT "price_estimates"."estimate_of_id" FROM "price_estimates" WHERE "price_estimates"."estimate_of_type" = 'Treasure')
27
+ ```
28
+
29
+ *Lázaro Nixon*
30
+
31
+ * Fix decrementing counter caches on optimistically locked record deletion
32
+
33
+ *fatkodima*
34
+
35
+ * Ensure binary-destined values have binary encoding during type cast.
36
+
37
+ *Matthew Draper*
38
+
39
+ * Preserve existing column default functions when altering table in SQLite.
40
+
41
+ *fatkodima*
42
+
43
+ * Remove table alias added when using `where.missing` or `where.associated`.
44
+
45
+ *fatkodima*
46
+
47
+ * Fix `Enumerable#in_order_of` to only flatten first level to preserve nesting.
48
+
49
+ *Miha Rekar*
50
+
51
+
52
+ ## Rails 7.0.5.1 (June 26, 2023) ##
53
+
54
+ * No changes.
55
+
1
56
  ## Rails 7.0.5 (May 24, 2023) ##
2
57
 
3
58
  * Type cast `#attribute_changed?` `:from` and `:to` options.
@@ -76,7 +131,7 @@
76
131
 
77
132
  *Shota Toguchi*, *Yusaku Ono*
78
133
 
79
- * Use connection from `#with_raw_connection` in `#quote_string`.
134
+ * Fix erroneous nil default precision on virtual datetime columns.
80
135
 
81
136
  Prior to this change, virtual datetime columns did not have the same
82
137
  default precision as regular datetime columns, resulting in the following
data/README.rdoc CHANGED
@@ -192,7 +192,7 @@ The latest version of Active Record can be installed with RubyGems:
192
192
 
193
193
  $ gem install activerecord
194
194
 
195
- Source code can be downloaded as part of the Rails project on GitHub:
195
+ Source code can be downloaded as part of the \Rails project on GitHub:
196
196
 
197
197
  * https://github.com/rails/rails/tree/main/activerecord
198
198
 
@@ -210,7 +210,7 @@ API documentation is at:
210
210
 
211
211
  * https://api.rubyonrails.org
212
212
 
213
- Bug reports for the Ruby on Rails project can be filed here:
213
+ Bug reports for the Ruby on \Rails project can be filed here:
214
214
 
215
215
  * https://github.com/rails/rails/issues
216
216
 
@@ -354,11 +354,15 @@ module ActiveRecord
354
354
  end
355
355
 
356
356
  def normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
357
- if indexed_attribute
358
- "#{reflection.name}[#{index}].#{attribute}"
359
- else
360
- "#{reflection.name}.#{attribute}"
361
- end
357
+ normalized_attribute =
358
+ if indexed_attribute
359
+ "#{reflection.name}[#{index}]"
360
+ else
361
+ reflection.name
362
+ end
363
+
364
+ normalized_attribute = "#{normalized_attribute}.#{attribute}" if attribute != :base
365
+ normalized_attribute
362
366
  end
363
367
 
364
368
  # Is used as an around_save callback to check while saving a collection
@@ -264,7 +264,7 @@ module ActiveRecord
264
264
  #
265
265
  # generates:
266
266
  #
267
- # CREATE TABLE order (
267
+ # CREATE TABLE orders (
268
268
  # product_id bigint NOT NULL,
269
269
  # client_id bigint NOT NULL
270
270
  # );
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
  fields.each_with_index do |fname, i|
58
58
  ftype = result.ftype i
59
59
  fmod = result.fmod i
60
- types[fname] = get_oid_type(ftype, fmod, fname)
60
+ types[fname] = types[i] = get_oid_type(ftype, fmod, fname)
61
61
  end
62
62
  build_result(columns: fields, rows: result.values, column_types: types)
63
63
  end
@@ -13,7 +13,7 @@ module ActiveRecord
13
13
  return if value.blank?
14
14
 
15
15
  time = super
16
- return time unless time.acts_like?(:time)
16
+ return time if time.is_a?(ActiveSupport::TimeWithZone) || !time.acts_like?(:time)
17
17
 
18
18
  # While in UTC mode, the PG gem may not return times back in "UTC" even if they were provided to Postgres in UTC.
19
19
  # We prefer times always in UTC, so here we convert back.
@@ -480,6 +480,7 @@ module ActiveRecord
480
480
  if column.has_default?
481
481
  type = lookup_cast_type_from_column(column)
482
482
  default = type.deserialize(column.default)
483
+ default = -> { column.default_function } if default.nil?
483
484
  end
484
485
 
485
486
  @definition.column(column_name, column.type,
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 5
12
+ TINY = 6
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -2,14 +2,14 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Locking
5
- # == What is Optimistic Locking
5
+ # == What is \Optimistic \Locking
6
6
  #
7
7
  # Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of
8
8
  # conflicts with the data. It does this by checking whether another process has made changes to a record since
9
- # it was opened, an <tt>ActiveRecord::StaleObjectError</tt> exception is thrown if that has occurred
9
+ # it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred
10
10
  # and the update is ignored.
11
11
  #
12
- # Check out <tt>ActiveRecord::Locking::Pessimistic</tt> for an alternative.
12
+ # Check out +ActiveRecord::Locking::Pessimistic+ for an alternative.
13
13
  #
14
14
  # == Usage
15
15
  #
@@ -69,6 +69,11 @@ module ActiveRecord
69
69
  end
70
70
  end
71
71
 
72
+ def initialize_dup(other) # :nodoc:
73
+ super
74
+ _clear_locking_column if locking_enabled?
75
+ end
76
+
72
77
  private
73
78
  def _create_record(attribute_names = self.attribute_names)
74
79
  if locking_enabled?
@@ -91,8 +96,7 @@ module ActiveRecord
91
96
  locking_column = self.class.locking_column
92
97
  lock_attribute_was = @attributes[locking_column]
93
98
 
94
- update_constraints = _primary_key_constraints_hash
95
- update_constraints[locking_column] = _lock_value_for_database(locking_column)
99
+ update_constraints = _query_constraints_hash
96
100
 
97
101
  attribute_names = attribute_names.dup if attribute_names.frozen?
98
102
  attribute_names << locking_column
@@ -118,16 +122,9 @@ module ActiveRecord
118
122
  end
119
123
 
120
124
  def destroy_row
121
- return super unless locking_enabled?
122
-
123
- locking_column = self.class.locking_column
125
+ affected_rows = super
124
126
 
125
- delete_constraints = _primary_key_constraints_hash
126
- delete_constraints[locking_column] = _lock_value_for_database(locking_column)
127
-
128
- affected_rows = self.class._delete_record(delete_constraints)
129
-
130
- if affected_rows != 1
127
+ if locking_enabled? && affected_rows != 1
131
128
  raise ActiveRecord::StaleObjectError.new(self, "destroy")
132
129
  end
133
130
 
@@ -142,6 +139,18 @@ module ActiveRecord
142
139
  end
143
140
  end
144
141
 
142
+ def _clear_locking_column
143
+ self[self.class.locking_column] = nil
144
+ clear_attribute_change(self.class.locking_column)
145
+ end
146
+
147
+ def _query_constraints_hash
148
+ return super unless locking_enabled?
149
+
150
+ locking_column = self.class.locking_column
151
+ super.merge(locking_column => _lock_value_for_database(locking_column))
152
+ end
153
+
145
154
  module ClassMethods
146
155
  DEFAULT_LOCKING_COLUMN = "lock_version"
147
156
 
@@ -159,10 +168,7 @@ module ActiveRecord
159
168
  end
160
169
 
161
170
  # The version column used for optimistic locking. Defaults to +lock_version+.
162
- def locking_column
163
- @locking_column = DEFAULT_LOCKING_COLUMN unless defined?(@locking_column)
164
- @locking_column
165
- end
171
+ attr_reader :locking_column
166
172
 
167
173
  # Reset the column used for optimistic locking back to the +lock_version+ default.
168
174
  def reset_locking_column
@@ -182,6 +188,14 @@ module ActiveRecord
182
188
  end
183
189
  super
184
190
  end
191
+
192
+ private
193
+ def inherited(base)
194
+ super
195
+ base.class_eval do
196
+ @locking_column = DEFAULT_LOCKING_COLUMN
197
+ end
198
+ end
185
199
  end
186
200
  end
187
201
 
@@ -813,7 +813,7 @@ module ActiveRecord
813
813
  verify_readonly_attribute(name) || name
814
814
  end
815
815
 
816
- update_constraints = _primary_key_constraints_hash
816
+ update_constraints = _query_constraints_hash
817
817
  attributes = attributes.each_with_object({}) do |(k, v), h|
818
818
  h[k] = @attributes.write_cast_value(k, v)
819
819
  clear_attribute_change(k)
@@ -1028,7 +1028,7 @@ module ActiveRecord
1028
1028
  (self.class.default_scopes?(all_queries: true) || self.class.global_current_scope)
1029
1029
  end
1030
1030
 
1031
- def _primary_key_constraints_hash
1031
+ def _query_constraints_hash
1032
1032
  { @primary_key => id_in_database }
1033
1033
  end
1034
1034
 
@@ -1041,7 +1041,7 @@ module ActiveRecord
1041
1041
  end
1042
1042
 
1043
1043
  def _delete_row
1044
- self.class._delete_record(_primary_key_constraints_hash)
1044
+ self.class._delete_record(_query_constraints_hash)
1045
1045
  end
1046
1046
 
1047
1047
  def _touch_row(attribute_names, time)
@@ -1057,7 +1057,7 @@ module ActiveRecord
1057
1057
  def _update_row(attribute_names, attempted_action = "update")
1058
1058
  self.class._update_record(
1059
1059
  attributes_with_values(attribute_names),
1060
- _primary_key_constraints_hash
1060
+ _query_constraints_hash
1061
1061
  )
1062
1062
  end
1063
1063
 
@@ -485,6 +485,10 @@ module ActiveRecord
485
485
  foreign_key
486
486
  end
487
487
 
488
+ def join_primary_type
489
+ type
490
+ end
491
+
488
492
  def join_foreign_key
489
493
  active_record_primary_key
490
494
  end
@@ -588,6 +592,10 @@ module ActiveRecord
588
592
  options[:polymorphic]
589
593
  end
590
594
 
595
+ def polymorphic_name
596
+ active_record.polymorphic_name
597
+ end
598
+
591
599
  def add_as_source(seed)
592
600
  seed
593
601
  end
@@ -18,7 +18,10 @@ module ActiveRecord
18
18
  def ids
19
19
  case value
20
20
  when Relation
21
- value.select_values.empty? ? value.select(primary_key) : value
21
+ relation = value
22
+ relation = relation.select(primary_key) if select_clause?
23
+ relation = relation.where(primary_type => polymorphic_name) if polymorphic_clause?
24
+ relation
22
25
  when Array
23
26
  value.map { |v| convert_to_id(v) }
24
27
  else
@@ -30,6 +33,22 @@ module ActiveRecord
30
33
  associated_table.join_primary_key
31
34
  end
32
35
 
36
+ def primary_type
37
+ associated_table.join_primary_type
38
+ end
39
+
40
+ def polymorphic_name
41
+ associated_table.polymorphic_name_association
42
+ end
43
+
44
+ def select_clause?
45
+ value.select_values.empty?
46
+ end
47
+
48
+ def polymorphic_clause?
49
+ primary_type && !value.where_values_hash.has_key?(primary_type)
50
+ end
51
+
33
52
  def convert_to_id(value)
34
53
  if value.respond_to?(primary_key)
35
54
  value.public_send(primary_key)
@@ -77,7 +77,11 @@ module ActiveRecord
77
77
  associations.each do |association|
78
78
  reflection = scope_association_reflection(association)
79
79
  @scope.joins!(association)
80
- self.not(association => { reflection.association_primary_key => nil })
80
+ if @scope.table_name == reflection.table_name
81
+ self.not(association => { reflection.association_primary_key => nil })
82
+ else
83
+ self.not(reflection.table_name => { reflection.association_primary_key => nil })
84
+ end
81
85
  end
82
86
 
83
87
  @scope
@@ -105,7 +109,11 @@ module ActiveRecord
105
109
  associations.each do |association|
106
110
  reflection = scope_association_reflection(association)
107
111
  @scope.left_outer_joins!(association)
108
- @scope.where!(association => { reflection.association_primary_key => nil })
112
+ if @scope.table_name == reflection.table_name
113
+ @scope.where!(association => { reflection.association_primary_key => nil })
114
+ else
115
+ @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
116
+ end
109
117
  end
110
118
 
111
119
  @scope
@@ -108,7 +108,7 @@ module ActiveRecord
108
108
  type = if type_overrides.is_a?(Array)
109
109
  type_overrides.first
110
110
  else
111
- column_type(columns.first, type_overrides)
111
+ column_type(columns.first, 0, type_overrides)
112
112
  end
113
113
 
114
114
  rows.map do |(value)|
@@ -118,7 +118,7 @@ module ActiveRecord
118
118
  types = if type_overrides.is_a?(Array)
119
119
  type_overrides
120
120
  else
121
- columns.map { |name| column_type(name, type_overrides) }
121
+ columns.map.with_index { |name, i| column_type(name, i, type_overrides) }
122
122
  end
123
123
 
124
124
  rows.map do |values|
@@ -135,9 +135,11 @@ module ActiveRecord
135
135
  end
136
136
 
137
137
  private
138
- def column_type(name, type_overrides = {})
138
+ def column_type(name, index, type_overrides)
139
139
  type_overrides.fetch(name) do
140
- column_types.fetch(name, Type.default_value)
140
+ column_types.fetch(index) do
141
+ column_types.fetch(name, Type.default_value)
142
+ end
141
143
  end
142
144
  end
143
145
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class TableMetadata # :nodoc:
5
- delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
5
+ delegate :join_primary_key, :join_primary_type, :join_foreign_key, :join_foreign_type, to: :reflection
6
6
 
7
7
  def initialize(klass, arel_table, reflection = nil)
8
8
  @klass = klass
@@ -54,6 +54,10 @@ module ActiveRecord
54
54
  reflection&.polymorphic?
55
55
  end
56
56
 
57
+ def polymorphic_name_association
58
+ reflection&.polymorphic_name
59
+ end
60
+
57
61
  def through_association?
58
62
  reflection&.through_reflection?
59
63
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.5
4
+ version: 7.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-05-24 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.5
19
+ version: 7.0.6
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.5
26
+ version: 7.0.6
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.0.5
33
+ version: 7.0.6
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.0.5
40
+ version: 7.0.6
41
41
  description: Databases on Rails. Build a persistent domain model by mapping database
42
42
  tables to Ruby classes. Strong conventions for associations, validations, aggregations,
43
43
  migrations, and testing come baked-in.
@@ -434,10 +434,10 @@ licenses:
434
434
  - MIT
435
435
  metadata:
436
436
  bug_tracker_uri: https://github.com/rails/rails/issues
437
- changelog_uri: https://github.com/rails/rails/blob/v7.0.5/activerecord/CHANGELOG.md
438
- documentation_uri: https://api.rubyonrails.org/v7.0.5/
437
+ changelog_uri: https://github.com/rails/rails/blob/v7.0.6/activerecord/CHANGELOG.md
438
+ documentation_uri: https://api.rubyonrails.org/v7.0.6/
439
439
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
440
- source_code_uri: https://github.com/rails/rails/tree/v7.0.5/activerecord
440
+ source_code_uri: https://github.com/rails/rails/tree/v7.0.6/activerecord
441
441
  rubygems_mfa_required: 'true'
442
442
  post_install_message:
443
443
  rdoc_options:
@@ -456,7 +456,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
456
456
  - !ruby/object:Gem::Version
457
457
  version: '0'
458
458
  requirements: []
459
- rubygems_version: 3.4.10
459
+ rubygems_version: 3.4.13
460
460
  signing_key:
461
461
  specification_version: 4
462
462
  summary: Object-relational mapper framework (part of Rails).