activerecord 6.1.0 → 6.1.3

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +195 -15
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/aggregations.rb +4 -4
  5. data/lib/active_record/association_relation.rb +10 -0
  6. data/lib/active_record/associations/association.rb +7 -7
  7. data/lib/active_record/associations/association_scope.rb +7 -5
  8. data/lib/active_record/associations/belongs_to_association.rb +7 -3
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
  10. data/lib/active_record/associations/builder/association.rb +23 -2
  11. data/lib/active_record/associations/builder/belongs_to.rb +2 -2
  12. data/lib/active_record/associations/has_many_association.rb +1 -1
  13. data/lib/active_record/associations/join_dependency/join_association.rb +8 -7
  14. data/lib/active_record/associations/join_dependency.rb +1 -1
  15. data/lib/active_record/associations.rb +6 -2
  16. data/lib/active_record/attributes.rb +1 -1
  17. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +4 -4
  18. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  19. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  20. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -0
  21. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +7 -1
  22. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -8
  23. data/lib/active_record/connection_adapters/mysql/quoting.rb +17 -2
  24. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +4 -1
  25. data/lib/active_record/connection_adapters/pool_config.rb +13 -3
  26. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  27. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  28. data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -8
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  30. data/lib/active_record/connection_handling.rb +20 -12
  31. data/lib/active_record/core.rb +42 -24
  32. data/lib/active_record/database_configurations/url_config.rb +1 -1
  33. data/lib/active_record/enum.rb +48 -28
  34. data/lib/active_record/fixtures.rb +5 -2
  35. data/lib/active_record/gem_version.rb +1 -1
  36. data/lib/active_record/locking/optimistic.rb +14 -4
  37. data/lib/active_record/log_subscriber.rb +3 -2
  38. data/lib/active_record/migration/compatibility.rb +2 -1
  39. data/lib/active_record/migration.rb +1 -1
  40. data/lib/active_record/model_schema.rb +4 -4
  41. data/lib/active_record/railties/console_sandbox.rb +2 -4
  42. data/lib/active_record/railties/databases.rake +13 -7
  43. data/lib/active_record/reflection.rb +1 -1
  44. data/lib/active_record/relation/finder_methods.rb +1 -1
  45. data/lib/active_record/relation/predicate_builder/association_query_value.rb +3 -3
  46. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +9 -5
  47. data/lib/active_record/relation/predicate_builder.rb +5 -6
  48. data/lib/active_record/relation/query_methods.rb +8 -5
  49. data/lib/active_record/relation/where_clause.rb +5 -5
  50. data/lib/active_record/relation.rb +1 -2
  51. data/lib/active_record/signed_id.rb +1 -1
  52. data/lib/active_record/table_metadata.rb +6 -3
  53. data/lib/active_record/tasks/database_tasks.rb +1 -0
  54. data/lib/active_record/transactions.rb +4 -2
  55. metadata +13 -13
@@ -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
@@ -162,7 +162,7 @@ module ActiveRecord
162
162
  # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>'Money'</tt>
163
163
  # <tt>has_many :clients</tt> returns <tt>'Client'</tt>
164
164
  def class_name
165
- @class_name ||= -(options[:class_name]&.to_s || derive_class_name)
165
+ @class_name ||= -(options[:class_name] || derive_class_name).to_s
166
166
  end
167
167
 
168
168
  # Returns a list of scopes that should be applied for this Reflection
@@ -326,7 +326,7 @@ module ActiveRecord
326
326
  # compared to the records in memory. If the relation is unloaded, an
327
327
  # efficient existence query is performed, as in #exists?.
328
328
  def include?(record)
329
- if loaded? || offset_value || limit_value
329
+ if loaded? || offset_value || limit_value || having_clause.any?
330
330
  records.include?(record)
331
331
  else
332
332
  record.is_a?(klass) && exists?(record.id)
@@ -9,7 +9,7 @@ module ActiveRecord
9
9
  end
10
10
 
11
11
  def queries
12
- [associated_table.join_foreign_key => ids]
12
+ [ associated_table.join_foreign_key => ids ]
13
13
  end
14
14
 
15
15
  private
@@ -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
@@ -9,11 +9,13 @@ module ActiveRecord
9
9
  end
10
10
 
11
11
  def queries
12
+ return [ associated_table.join_foreign_key => values ] if values.empty?
13
+
12
14
  type_to_ids_mapping.map do |type, ids|
13
- {
14
- associated_table.join_foreign_type => type,
15
- associated_table.join_foreign_key => ids
16
- }
15
+ query = {}
16
+ query[associated_table.join_foreign_type] = type if type
17
+ query[associated_table.join_foreign_key] = ids
18
+ query
17
19
  end
18
20
  end
19
21
 
@@ -23,7 +25,7 @@ module ActiveRecord
23
25
  def type_to_ids_mapping
24
26
  default_hash = Hash.new { |hsh, key| hsh[key] = [] }
25
27
  values.each_with_object(default_hash) do |value, hash|
26
- hash[klass(value).polymorphic_name] << convert_to_id(value)
28
+ hash[klass(value)&.polymorphic_name] << convert_to_id(value)
27
29
  end
28
30
  end
29
31
 
@@ -46,6 +48,8 @@ module ActiveRecord
46
48
  value._read_attribute(primary_key(value))
47
49
  when Relation
48
50
  value.select(primary_key(value))
51
+ else
52
+ value
49
53
  end
50
54
  end
51
55
  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
@@ -106,7 +103,9 @@ module ActiveRecord
106
103
 
107
104
  klass ||= AssociationQueryValue
108
105
  queries = klass.new(associated_table, value).queries.map! do |query|
109
- expand_from_hash(query)
106
+ # If the query produced is identical to attributes don't go any deeper.
107
+ # Prevents stack level too deep errors when association and foreign_key are identical.
108
+ query == attributes ? self[key, value] : expand_from_hash(query)
110
109
  end
111
110
 
112
111
  grouping_queries(queries)
@@ -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
@@ -58,8 +58,8 @@ module ActiveRecord
58
58
  end
59
59
  end
60
60
 
61
- def to_h(table_name = nil)
62
- equalities(predicates).each_with_object({}) do |node, hash|
61
+ def to_h(table_name = nil, equality_only: false)
62
+ equalities(predicates, equality_only).each_with_object({}) do |node, hash|
63
63
  next if table_name&.!= node.left.relation.name
64
64
  name = node.left.name.to_s
65
65
  value = extract_node_value(node.right)
@@ -134,14 +134,14 @@ module ActiveRecord
134
134
  attr_node
135
135
  end
136
136
 
137
- def equalities(predicates)
137
+ def equalities(predicates, equality_only)
138
138
  equalities = []
139
139
 
140
140
  predicates.each do |node|
141
- if equality_node?(node)
141
+ if equality_only ? Arel::Nodes::Equality === node : equality_node?(node)
142
142
  equalities << node
143
143
  elsif node.is_a?(Arel::Nodes::And)
144
- equalities.concat equalities(node.children)
144
+ equalities.concat equalities(node.children, equality_only)
145
145
  end
146
146
  end
147
147
 
@@ -683,8 +683,7 @@ module ActiveRecord
683
683
  end
684
684
 
685
685
  def scope_for_create
686
- hash = where_values_hash
687
- hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
686
+ hash = where_clause.to_h(klass.table_name, equality_only: true)
688
687
  create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
689
688
  hash
690
689
  end
@@ -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.3
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-02-17 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.3
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.3
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.3
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.3
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.3/activerecord/CHANGELOG.md
394
+ documentation_uri: https://api.rubyonrails.org/v6.1.3/
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.3/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: []