activerecord 6.1.0 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -15
  3. data/lib/active_record/aggregations.rb +4 -4
  4. data/lib/active_record/associations.rb +6 -2
  5. data/lib/active_record/associations/association_scope.rb +7 -5
  6. data/lib/active_record/associations/belongs_to_association.rb +7 -3
  7. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  8. data/lib/active_record/associations/builder/belongs_to.rb +2 -2
  9. data/lib/active_record/associations/has_many_association.rb +1 -1
  10. data/lib/active_record/associations/join_dependency/join_association.rb +8 -7
  11. data/lib/active_record/attributes.rb +1 -1
  12. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +7 -1
  13. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  14. data/lib/active_record/enum.rb +41 -27
  15. data/lib/active_record/fixtures.rb +4 -1
  16. data/lib/active_record/gem_version.rb +1 -1
  17. data/lib/active_record/migration/compatibility.rb +2 -1
  18. data/lib/active_record/railties/databases.rake +13 -7
  19. data/lib/active_record/relation/predicate_builder.rb +2 -5
  20. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
  21. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +7 -5
  22. data/lib/active_record/relation/query_methods.rb +8 -5
  23. data/lib/active_record/signed_id.rb +1 -1
  24. data/lib/active_record/table_metadata.rb +6 -3
  25. data/lib/active_record/tasks/database_tasks.rb +1 -0
  26. data/lib/active_record/transactions.rb +4 -2
  27. metadata +13 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 418812373f3ff5fd16133fe0928b94b80b78b8a366abfc23a205fcb2ccc5a3e3
4
- data.tar.gz: 70db1902a8fc82b1c46f8a7731ffb358357bc8cac29564a57881a732dbd2a65a
3
+ metadata.gz: 56f128436e13685f9715b6dbe295150f61a11e7af686fc5d758044f080fe1879
4
+ data.tar.gz: b80991c1de4020e4e770f64464683e6e3cd88f38dbc93e8909c270ade9f32d20
5
5
  SHA512:
6
- metadata.gz: 31ae64f629cb62f63bc37c74a888d557f9f0b102d401f2f9cf62c7d31655d99e5161ae9bc7f8be874c7a9cf27ec879dde3c04075df5cb2b5868891c0db144a50
7
- data.tar.gz: cfc9585f3a6f53187707a9d96503269e3d4b1c5f1fe8c5f4db3bdefe8ce636042b6cf1fe9fb233491d1e8197f52293a7018a2f9925f1e34644ad1e30b134d59f
6
+ metadata.gz: 10f8bd5fccf212ad4807ae6c08a8264333af73373606dce2eb2338e2f6edcfa7469351f5a905836e4be6764548e580d0c205564c8aa2493cbb1476f02ed555a4
7
+ data.tar.gz: 2ff2988d43a99595a0a14d796afeca8aa53b54a8f7e516721a026a053cdc7bb0c23fcf934d180a165023b58c5e9335d42bb1c0e0b9daf1b6df078c1e969fc8c1
@@ -1,3 +1,63 @@
1
+ ## Rails 6.1.1 (January 07, 2021) ##
2
+
3
+ * Fix fixtures loading when strict loading is enabled for the association.
4
+
5
+ *Alex Ghiculescu*
6
+
7
+ * Fix `where` with custom primary key for belongs_to association.
8
+
9
+ *Ryuta Kamizono*
10
+
11
+ * Fix `where` with aliased associations.
12
+
13
+ *Ryuta Kamizono*
14
+
15
+ * Fix `composed_of` with symbol mapping.
16
+
17
+ *Ryuta Kamizono*
18
+
19
+ * Don't skip money's type cast for pluck and calculations.
20
+
21
+ *Ryuta Kamizono*
22
+
23
+ * Fix `where` on polymorphic association with non Active Record object.
24
+
25
+ *Ryuta Kamizono*
26
+
27
+ * Make sure `db:prepare` works even the schema file doesn't exist.
28
+
29
+ *Rafael Mendonça França*
30
+
31
+ * Fix complicated `has_many :through` with nested where condition.
32
+
33
+ *Ryuta Kamizono*
34
+
35
+ * Handle STI models for `has_many dependent: :destroy_async`.
36
+
37
+ *Muhammad Usman*
38
+
39
+ * Restore possibility of passing `false` to :polymorphic option of `belongs_to`.
40
+
41
+ Previously, passing `false` would trigger the option validation logic
42
+ to throw an error saying :polymorphic would not be a valid option.
43
+
44
+ *glaszig*
45
+
46
+ * Allow adding nonnamed expression indexes to be revertible.
47
+
48
+ Fixes #40732.
49
+
50
+ Previously, the following code would raise an error, when executed while rolling back,
51
+ and the index name should be specified explicitly. Now, the index name is inferred
52
+ automatically.
53
+
54
+ ```ruby
55
+ add_index(:items, "to_tsvector('english', description)")
56
+ ```
57
+
58
+ *fatkodima*
59
+
60
+
1
61
  ## Rails 6.1.0 (December 09, 2020) ##
2
62
 
3
63
  * Only warn about negative enums if a positive form that would cause conflicts exists.
@@ -38,21 +98,21 @@
38
98
 
39
99
  Before:
40
100
 
41
- AnimalsRecord.connected_to(role: :reading) do
42
- MealsRecord.connected_to(role: :reading) do
43
- Dog.first # read from animals replica
44
- Dinner.first # read from meals replica
45
- Person.first # read from primary writer
101
+ AnimalsRecord.connected_to(role: :reading) do
102
+ MealsRecord.connected_to(role: :reading) do
103
+ Dog.first # read from animals replica
104
+ Dinner.first # read from meals replica
105
+ Person.first # read from primary writer
106
+ end
46
107
  end
47
- end
48
108
 
49
109
  After:
50
110
 
51
- ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do
52
- Dog.first # read from animals replica
53
- Dinner.first # read from meals replica
54
- Person.first # read from primary writer
55
- end
111
+ ActiveRecord::Base.connected_to_many([AnimalsRecord, MealsRecord], role: :reading) do
112
+ Dog.first # read from animals replica
113
+ Dinner.first # read from meals replica
114
+ Person.first # read from primary writer
115
+ end
56
116
 
57
117
  *Eileen M. Uchitelle*, *John Crepezzi*
58
118
 
@@ -170,13 +230,13 @@
170
230
 
171
231
  Before:
172
232
 
173
- User.where.not(name: "Jon", role: "admin")
174
- # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
233
+ User.where.not(name: "Jon", role: "admin")
234
+ # SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
175
235
 
176
236
  After:
177
237
 
178
- User.where.not(name: "Jon", role: "admin")
179
- # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
238
+ User.where.not(name: "Jon", role: "admin")
239
+ # SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
180
240
 
181
241
  *Rafael Mendonça França*
182
242
 
@@ -244,8 +244,8 @@ module ActiveRecord
244
244
  private
245
245
  def reader_method(name, class_name, mapping, allow_nil, constructor)
246
246
  define_method(name) do
247
- if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !_read_attribute(key).nil? })
248
- attrs = mapping.collect { |key, _| _read_attribute(key) }
247
+ if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? { |key, _| !read_attribute(key).nil? })
248
+ attrs = mapping.collect { |key, _| read_attribute(key) }
249
249
  object = constructor.respond_to?(:call) ?
250
250
  constructor.call(*attrs) :
251
251
  class_name.constantize.send(constructor, *attrs)
@@ -271,10 +271,10 @@ module ActiveRecord
271
271
  end
272
272
 
273
273
  if part.nil? && allow_nil
274
- mapping.each { |key, _| self[key] = nil }
274
+ mapping.each { |key, _| write_attribute(key, nil) }
275
275
  @aggregation_cache[name] = nil
276
276
  else
277
- mapping.each { |key, value| self[key] = part.send(value) }
277
+ mapping.each { |key, value| write_attribute(key, part.send(value)) }
278
278
  @aggregation_cache[name] = part.freeze
279
279
  end
280
280
  end
@@ -1371,7 +1371,9 @@ module ActiveRecord
1371
1371
  #
1372
1372
  # * <tt>nil</tt> do nothing (default).
1373
1373
  # * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
1374
- # * <tt>:destroy_async</tt> destroys all the associated objects in a background job.
1374
+ # * <tt>:destroy_async</tt> destroys all the associated objects in a background job. <b>WARNING:</b> Do not use
1375
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1376
+ # constraint actions will occur inside the same transaction that deletes its owner.
1375
1377
  # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
1376
1378
  # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
1377
1379
  # on polymorphic associations. Callbacks are not executed.
@@ -1523,7 +1525,9 @@ module ActiveRecord
1523
1525
  #
1524
1526
  # * <tt>nil</tt> do nothing (default).
1525
1527
  # * <tt>:destroy</tt> causes the associated object to also be destroyed
1526
- # * <tt>:destroy_async</tt> causes all the associated object to be destroyed in a background job.
1528
+ # * <tt>:destroy_async</tt> causes the associated object to be destroyed in a background job. <b>WARNING:</b> Do not use
1529
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1530
+ # constraint actions will occur inside the same transaction that deletes its owner.
1527
1531
  # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
1528
1532
  # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
1529
1533
  # on polymorphic associations. Callbacks are not executed.
@@ -131,11 +131,13 @@ module ActiveRecord
131
131
  if scope_chain_item == chain_head.scope
132
132
  scope.merge! item.except(:where, :includes, :unscope, :order)
133
133
  elsif !item.references_values.empty?
134
- join_dependency = item.construct_join_dependency(
135
- item.eager_load_values | item.includes_values, Arel::Nodes::OuterJoin
136
- )
137
- scope.joins!(*item.joins_values, join_dependency)
138
- scope.left_outer_joins!(*item.left_outer_joins_values)
134
+ scope.merge! item.only(:joins, :left_outer_joins)
135
+
136
+ associations = item.eager_load_values | item.includes_values
137
+
138
+ unless associations.empty?
139
+ scope.joins! item.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
140
+ end
139
141
  end
140
142
 
141
143
  reflection.all_includes do
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
  @updated = true
81
81
  end
82
82
 
83
- replace_keys(record)
83
+ replace_keys(record, force: true)
84
84
 
85
85
  self.target = record
86
86
  end
@@ -108,8 +108,12 @@ module ActiveRecord
108
108
  reflection.counter_cache_column && owner.persisted?
109
109
  end
110
110
 
111
- def replace_keys(record)
112
- owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record.class)) : nil
111
+ def replace_keys(record, force: false)
112
+ target_key = record ? record._read_attribute(primary_key(record.class)) : nil
113
+
114
+ if force || owner[reflection.foreign_key] != target_key
115
+ owner[reflection.foreign_key] = target_key
116
+ end
113
117
  end
114
118
 
115
119
  def primary_key(klass)
@@ -14,9 +14,14 @@ module ActiveRecord
14
14
  end
15
15
 
16
16
  private
17
- def replace_keys(record)
17
+ def replace_keys(record, force: false)
18
18
  super
19
- owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
19
+
20
+ target_type = record ? record.class.polymorphic_name : nil
21
+
22
+ if force || owner[reflection.foreign_type] != target_type
23
+ owner[reflection.foreign_type] = target_type
24
+ end
20
25
  end
21
26
 
22
27
  def inverse_reflection_for(record)
@@ -7,8 +7,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
7
7
  end
8
8
 
9
9
  def self.valid_options(options)
10
- valid = super + [:counter_cache, :optional, :default]
11
- valid += [:polymorphic, :foreign_type] if options[:polymorphic]
10
+ valid = super + [:polymorphic, :counter_cache, :optional, :default]
11
+ valid += [:foreign_type] if options[:polymorphic]
12
12
  valid += [:ensuring_owner_was] if options[:dependent] == :destroy_async
13
13
  valid
14
14
  end
@@ -42,7 +42,7 @@ module ActiveRecord
42
42
  enqueue_destroy_association(
43
43
  owner_model_name: owner.class.to_s,
44
44
  owner_id: owner.id,
45
- association_class: association_class.to_s,
45
+ association_class: reflection.klass.to_s,
46
46
  association_ids: ids,
47
47
  association_primary_key_column: primary_key_column,
48
48
  ensuring_owner_was_method: options.fetch(:ensuring_owner_was, nil)
@@ -42,16 +42,17 @@ module ActiveRecord
42
42
  chain.reverse_each do |reflection, table|
43
43
  klass = reflection.klass
44
44
 
45
- join_scope = reflection.join_scope(table, foreign_table, foreign_klass)
45
+ scope = reflection.join_scope(table, foreign_table, foreign_klass)
46
46
 
47
- unless join_scope.references_values.empty?
48
- join_dependency = join_scope.construct_join_dependency(
49
- join_scope.eager_load_values | join_scope.includes_values, Arel::Nodes::OuterJoin
50
- )
51
- join_scope.joins!(join_dependency)
47
+ unless scope.references_values.empty?
48
+ associations = scope.eager_load_values | scope.includes_values
49
+
50
+ unless associations.empty?
51
+ scope.joins! scope.construct_join_dependency(associations, Arel::Nodes::OuterJoin)
52
+ end
52
53
  end
53
54
 
54
- arel = join_scope.arel(alias_tracker.aliases)
55
+ arel = scope.arel(alias_tracker.aliases)
55
56
  nodes = arel.constraints.first
56
57
 
57
58
  if nodes.is_a?(Arel::Nodes::And)
@@ -173,7 +173,7 @@ module ActiveRecord
173
173
  # class Money < Struct.new(:amount, :currency)
174
174
  # end
175
175
  #
176
- # class MoneyType < Type::Value
176
+ # class MoneyType < ActiveRecord::Type::Value
177
177
  # def initialize(currency_converter:)
178
178
  # @currency_converter = currency_converter
179
179
  # end
@@ -1387,8 +1387,14 @@ module ActiveRecord
1387
1387
 
1388
1388
  checks = []
1389
1389
 
1390
+ if !options.key?(:name) && column_name.is_a?(String) && /\W/.match?(column_name)
1391
+ options[:name] = index_name(table_name, column_name)
1392
+ column_names = []
1393
+ else
1394
+ column_names = index_column_names(column_name || options[:column])
1395
+ end
1396
+
1390
1397
  checks << lambda { |i| i.name == options[:name].to_s } if options.key?(:name)
1391
- column_names = index_column_names(column_name || options[:column])
1392
1398
 
1393
1399
  if column_names.present?
1394
1400
  checks << lambda { |i| index_name(table_name, i.columns) == index_name(table_name, column_names) }
@@ -57,7 +57,7 @@ module ActiveRecord
57
57
  ftype = result.ftype i
58
58
  fmod = result.fmod i
59
59
  case type = get_oid_type(ftype, fmod, fname)
60
- when Type::Integer, Type::Float, Type::Decimal, Type::String, Type::DateTime, Type::Boolean
60
+ when Type::Integer, Type::Float, OID::Decimal, Type::String, Type::DateTime, Type::Boolean
61
61
  # skip if a column has already been type casted by pg decoders
62
62
  else types[fname] = type
63
63
  end
@@ -158,8 +158,6 @@ module ActiveRecord
158
158
  end
159
159
 
160
160
  def enum(definitions)
161
- klass = self
162
-
163
161
  enum_prefix = definitions.delete(:_prefix)
164
162
  enum_suffix = definitions.delete(:_suffix)
165
163
  enum_scopes = definitions.delete(:_scopes)
@@ -187,55 +185,71 @@ module ActiveRecord
187
185
  EnumType.new(attr, enum_values, subtype)
188
186
  end
189
187
 
188
+ value_method_names = []
190
189
  _enum_methods_module.module_eval do
190
+ enum_prefix = name if enum_prefix == true
191
+ prefix = "#{enum_prefix}_" if enum_prefix
192
+
193
+ enum_suffix = name if enum_suffix == true
194
+ suffix = "_#{enum_suffix}" if enum_suffix
195
+
191
196
  pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
192
- value_method_names = []
193
197
  pairs.each do |label, value|
194
- if enum_prefix == true
195
- prefix = "#{name}_"
196
- elsif enum_prefix
197
- prefix = "#{enum_prefix}_"
198
- end
199
- if enum_suffix == true
200
- suffix = "_#{name}"
201
- elsif enum_suffix
202
- suffix = "_#{enum_suffix}"
203
- end
198
+ label = label.to_s
199
+ enum_values[label] = value
204
200
 
205
- method_friendly_label = label.to_s.gsub(/\W+/, "_")
206
- value_method_name = "#{prefix}#{method_friendly_label}#{suffix}"
201
+ value_method_name = "#{prefix}#{label}#{suffix}"
207
202
  value_method_names << value_method_name
208
- enum_values[label] = value
209
- label = label.to_s
203
+ define_enum_methods(name, value_method_name, label, enum_scopes)
204
+
205
+ method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
206
+ value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
210
207
 
208
+ if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
209
+ value_method_names << value_method_alias
210
+ define_enum_methods(name, value_method_alias, label, enum_scopes)
211
+ end
212
+ end
213
+ end
214
+ detect_negative_enum_conditions!(value_method_names) if enum_scopes != false
215
+ enum_values.freeze
216
+ end
217
+ end
218
+
219
+ private
220
+ class EnumMethods < Module # :nodoc:
221
+ def initialize(klass)
222
+ @klass = klass
223
+ end
224
+
225
+ private
226
+ attr_reader :klass
227
+
228
+ def define_enum_methods(name, value_method_name, label, enum_scopes)
211
229
  # def active?() status == "active" end
212
230
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
213
- define_method("#{value_method_name}?") { self[attr] == label }
231
+ define_method("#{value_method_name}?") { self[name] == label }
214
232
 
215
233
  # def active!() update!(status: 0) end
216
234
  klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
217
- define_method("#{value_method_name}!") { update!(attr => value) }
235
+ define_method("#{value_method_name}!") { update!(name => label) }
218
236
 
219
237
  # scope :active, -> { where(status: 0) }
220
238
  # scope :not_active, -> { where.not(status: 0) }
221
239
  if enum_scopes != false
222
240
  klass.send(:detect_enum_conflict!, name, value_method_name, true)
223
- klass.scope value_method_name, -> { where(attr => value) }
241
+ klass.scope value_method_name, -> { where(name => label) }
224
242
 
225
243
  klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
226
- klass.scope "not_#{value_method_name}", -> { where.not(attr => value) }
244
+ klass.scope "not_#{value_method_name}", -> { where.not(name => label) }
227
245
  end
228
246
  end
229
- klass.send(:detect_negative_enum_conditions!, value_method_names) if enum_scopes != false
230
- end
231
- enum_values.freeze
232
247
  end
233
- end
248
+ private_constant :EnumMethods
234
249
 
235
- private
236
250
  def _enum_methods_module
237
251
  @_enum_methods_module ||= begin
238
- mod = Module.new
252
+ mod = EnumMethods.new(self)
239
253
  include mod
240
254
  mod
241
255
  end
@@ -773,9 +773,12 @@ module ActiveRecord
773
773
 
774
774
  def find
775
775
  raise FixtureClassNotFound, "No class attached to find." unless model_class
776
- model_class.unscoped do
776
+ object = model_class.unscoped do
777
777
  model_class.find(fixture[model_class.primary_key])
778
778
  end
779
+ # Fixtures can't be eagerly loaded
780
+ object.instance_variable_set(:@strict_loading, false)
781
+ object
779
782
  end
780
783
  end
781
784
  end
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 6
11
11
  MINOR = 1
12
- TINY = 0
12
+ TINY = 1
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -56,7 +56,8 @@ module ActiveRecord
56
56
  end
57
57
 
58
58
  def add_reference(table_name, ref_name, **options)
59
- ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
59
+ ReferenceDefinition.new(ref_name, **options)
60
+ .add_to(connection.update_table_definition(table_name, self))
60
61
  end
61
62
  alias :add_belongs_to :add_reference
62
63
 
@@ -361,17 +361,23 @@ db_namespace = namespace :db do
361
361
 
362
362
  # Skipped when no database
363
363
  ActiveRecord::Tasks::DatabaseTasks.migrate
364
+
364
365
  if ActiveRecord::Base.dump_schema_after_migration
365
366
  ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ActiveRecord::Base.schema_format)
366
367
  end
367
-
368
368
  rescue ActiveRecord::NoDatabaseError
369
- ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, db_config.name)
370
- ActiveRecord::Tasks::DatabaseTasks.load_schema(
371
- db_config,
372
- ActiveRecord::Base.schema_format,
373
- nil
374
- )
369
+ config_name = db_config.name
370
+ ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, config_name)
371
+
372
+ if File.exist?(ActiveRecord::Tasks::DatabaseTasks.dump_filename(config_name))
373
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(
374
+ db_config,
375
+ ActiveRecord::Base.schema_format,
376
+ nil
377
+ )
378
+ else
379
+ ActiveRecord::Tasks::DatabaseTasks.migrate
380
+ end
375
381
 
376
382
  seed = true
377
383
  end
@@ -93,11 +93,8 @@ module ActiveRecord
93
93
  # PriceEstimate.where(estimate_of: treasure)
94
94
  associated_table = table.associated_table(key)
95
95
  if associated_table.polymorphic_association?
96
- case value.is_a?(Array) ? value.first : value
97
- when Base, Relation
98
- value = [value] unless value.is_a?(Array)
99
- klass = PolymorphicArrayValue
100
- end
96
+ value = [value] unless value.is_a?(Array)
97
+ klass = PolymorphicArrayValue
101
98
  elsif associated_table.through_association?
102
99
  next associated_table.predicate_builder.expand_from_hash(
103
100
  associated_table.primary_key => value
@@ -31,8 +31,8 @@ module ActiveRecord
31
31
  end
32
32
 
33
33
  def convert_to_id(value)
34
- if value.respond_to?(:id)
35
- value.id
34
+ if value.respond_to?(primary_key)
35
+ value.public_send(primary_key)
36
36
  else
37
37
  value
38
38
  end
@@ -10,10 +10,10 @@ module ActiveRecord
10
10
 
11
11
  def queries
12
12
  type_to_ids_mapping.map do |type, ids|
13
- {
14
- associated_table.join_foreign_type => type,
15
- associated_table.join_foreign_key => ids
16
- }
13
+ query = {}
14
+ query[associated_table.join_foreign_type] = type if type
15
+ query[associated_table.join_foreign_key] = ids
16
+ query
17
17
  end
18
18
  end
19
19
 
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  def type_to_ids_mapping
24
24
  default_hash = Hash.new { |hsh, key| hsh[key] = [] }
25
25
  values.each_with_object(default_hash) do |value, hash|
26
- hash[klass(value).polymorphic_name] << convert_to_id(value)
26
+ hash[klass(value)&.polymorphic_name] << convert_to_id(value)
27
27
  end
28
28
  end
29
29
 
@@ -46,6 +46,8 @@ module ActiveRecord
46
46
  value._read_attribute(primary_key(value))
47
47
  when Relation
48
48
  value.select(primary_key(value))
49
+ else
50
+ value
49
51
  end
50
52
  end
51
53
  end
@@ -1081,12 +1081,15 @@ module ActiveRecord
1081
1081
  when String, Array
1082
1082
  parts = [klass.sanitize_sql(rest.empty? ? opts : [opts, *rest])]
1083
1083
  when Hash
1084
- opts = opts.stringify_keys
1084
+ opts = opts.transform_keys do |key|
1085
+ key = key.to_s
1086
+ klass.attribute_aliases[key] || key
1087
+ end
1085
1088
  references = PredicateBuilder.references(opts)
1086
1089
  self.references_values |= references unless references.empty?
1087
1090
 
1088
1091
  parts = predicate_builder.build_from_hash(opts) do |table_name|
1089
- lookup_reflection_from_join_dependencies(table_name)
1092
+ lookup_table_klass_from_join_dependencies(table_name)
1090
1093
  end
1091
1094
  when Arel::Nodes::Node
1092
1095
  parts = [opts]
@@ -1099,9 +1102,9 @@ module ActiveRecord
1099
1102
  alias :build_having_clause :build_where_clause
1100
1103
 
1101
1104
  private
1102
- def lookup_reflection_from_join_dependencies(table_name)
1105
+ def lookup_table_klass_from_join_dependencies(table_name)
1103
1106
  each_join_dependencies do |join|
1104
- return join.reflection if table_name == join.table_name
1107
+ return join.base_klass if table_name == join.table_name
1105
1108
  end
1106
1109
  nil
1107
1110
  end
@@ -1312,7 +1315,7 @@ module ActiveRecord
1312
1315
  elsif field.match?(/\A\w+\.\w+\z/)
1313
1316
  table, column = field.split(".")
1314
1317
  predicate_builder.resolve_arel_attribute(table, column) do
1315
- lookup_reflection_from_join_dependencies(table)
1318
+ lookup_table_klass_from_join_dependencies(table)
1316
1319
  end
1317
1320
  else
1318
1321
  yield field
@@ -20,7 +20,7 @@ module ActiveRecord
20
20
  # a certain time period.
21
21
  #
22
22
  # You set the time period that the signed id is valid for during generation, using the instance method
23
- # +signed_id(expires_in: 15.minutes)+. If the time has elapsed before a signed find is attempted,
23
+ # <tt>signed_id(expires_in: 15.minutes)</tt>. If the time has elapsed before a signed find is attempted,
24
24
  # the signed id will no longer be valid, and nil is returned.
25
25
  #
26
26
  # It's possible to further restrict the use of a signed id with a purpose. This helps when you have a
@@ -33,10 +33,13 @@ module ActiveRecord
33
33
  return self
34
34
  end
35
35
 
36
- reflection ||= yield table_name if block_given?
36
+ if reflection
37
+ association_klass = reflection.klass unless reflection.polymorphic?
38
+ elsif block_given?
39
+ association_klass = yield table_name
40
+ end
37
41
 
38
- if reflection && !reflection.polymorphic?
39
- association_klass = reflection.klass
42
+ if association_klass
40
43
  arel_table = association_klass.arel_table
41
44
  arel_table = arel_table.alias(table_name) if arel_table.name != table_name
42
45
  TableMetadata.new(association_klass, arel_table, reflection)
@@ -380,6 +380,7 @@ module ActiveRecord
380
380
  filename = dump_filename(db_config.name, format)
381
381
  connection = ActiveRecord::Base.connection
382
382
 
383
+ FileUtils.mkdir_p(db_dir)
383
384
  case format
384
385
  when :ruby
385
386
  File.open(filename, "w:utf-8") do |file|
@@ -271,8 +271,10 @@ module ActiveRecord
271
271
  if options[:on]
272
272
  fire_on = Array(options[:on])
273
273
  assert_valid_transaction_action(fire_on)
274
- options[:if] = Array(options[:if])
275
- options[:if].unshift(-> { transaction_include_any_action?(fire_on) })
274
+ options[:if] = [
275
+ -> { transaction_include_any_action?(fire_on) },
276
+ *options[:if]
277
+ ]
276
278
  end
277
279
  end
278
280
 
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: 6.1.0
4
+ version: 6.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-09 00:00:00.000000000 Z
11
+ date: 2021-01-07 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: 6.1.0
19
+ version: 6.1.1
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: 6.1.0
26
+ version: 6.1.1
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: 6.1.0
33
+ version: 6.1.1
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: 6.1.0
40
+ version: 6.1.1
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.
@@ -390,11 +390,11 @@ licenses:
390
390
  - MIT
391
391
  metadata:
392
392
  bug_tracker_uri: https://github.com/rails/rails/issues
393
- changelog_uri: https://github.com/rails/rails/blob/v6.1.0/activerecord/CHANGELOG.md
394
- documentation_uri: https://api.rubyonrails.org/v6.1.0/
393
+ changelog_uri: https://github.com/rails/rails/blob/v6.1.1/activerecord/CHANGELOG.md
394
+ documentation_uri: https://api.rubyonrails.org/v6.1.1/
395
395
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
396
- source_code_uri: https://github.com/rails/rails/tree/v6.1.0/activerecord
397
- post_install_message:
396
+ source_code_uri: https://github.com/rails/rails/tree/v6.1.1/activerecord
397
+ post_install_message:
398
398
  rdoc_options:
399
399
  - "--main"
400
400
  - README.rdoc
@@ -411,8 +411,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
411
411
  - !ruby/object:Gem::Version
412
412
  version: '0'
413
413
  requirements: []
414
- rubygems_version: 3.1.4
415
- signing_key:
414
+ rubygems_version: 3.2.3
415
+ signing_key:
416
416
  specification_version: 4
417
417
  summary: Object-relational mapper framework (part of Rails).
418
418
  test_files: []