activerecord 6.0.3.7 → 6.0.4

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +108 -0
  3. data/README.rdoc +1 -1
  4. data/lib/active_record/associations/association.rb +2 -3
  5. data/lib/active_record/associations/association_scope.rb +7 -1
  6. data/lib/active_record/associations/collection_association.rb +7 -0
  7. data/lib/active_record/associations/collection_proxy.rb +1 -0
  8. data/lib/active_record/associations/join_dependency.rb +14 -6
  9. data/lib/active_record/associations/join_dependency/join_association.rb +7 -0
  10. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  11. data/lib/active_record/associations/preloader.rb +6 -2
  12. data/lib/active_record/associations/preloader/association.rb +41 -23
  13. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  14. data/lib/active_record/associations/through_association.rb +1 -1
  15. data/lib/active_record/autosave_association.rb +10 -10
  16. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -0
  17. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -1
  18. data/lib/active_record/connection_adapters/abstract_adapter.rb +6 -0
  19. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +9 -4
  20. data/lib/active_record/connection_adapters/mysql/database_statements.rb +1 -1
  21. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -4
  22. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +1 -1
  23. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  24. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -5
  25. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +1 -1
  26. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +1 -1
  27. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -1
  28. data/lib/active_record/core.rb +5 -6
  29. data/lib/active_record/enum.rb +13 -6
  30. data/lib/active_record/fixture_set/render_context.rb +1 -1
  31. data/lib/active_record/gem_version.rb +2 -2
  32. data/lib/active_record/insert_all.rb +1 -1
  33. data/lib/active_record/locking/optimistic.rb +9 -0
  34. data/lib/active_record/model_schema.rb +29 -0
  35. data/lib/active_record/reflection.rb +11 -13
  36. data/lib/active_record/relation.rb +6 -3
  37. data/lib/active_record/relation/calculations.rb +1 -1
  38. data/lib/active_record/relation/delegation.rb +2 -1
  39. data/lib/active_record/relation/finder_methods.rb +1 -1
  40. data/lib/active_record/relation/merger.rb +7 -2
  41. data/lib/active_record/relation/query_methods.rb +23 -11
  42. data/lib/active_record/scoping/named.rb +5 -0
  43. data/lib/active_record/test_fixtures.rb +19 -1
  44. data/lib/active_record/type/time.rb +10 -0
  45. data/lib/active_record/validations/associated.rb +1 -1
  46. metadata +12 -12
@@ -497,8 +497,8 @@ module ActiveRecord
497
497
  update_all updates
498
498
  end
499
499
 
500
- # Touches all records in the current relation without instantiating records first with the +updated_at+/+updated_on+ attributes
501
- # set to the current time or the time specified.
500
+ # Touches all records in the current relation, setting the +updated_at+/+updated_on+ attributes to the current time or the time specified.
501
+ # It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations.
502
502
  # This method can be passed attribute names and an optional time argument.
503
503
  # If attribute names are passed, they are updated along with +updated_at+/+updated_on+ attributes.
504
504
  # If no time argument is passed, the current time is used as default.
@@ -671,7 +671,10 @@ module ActiveRecord
671
671
  end
672
672
 
673
673
  def scope_for_create
674
- where_values_hash.merge!(create_with_value.stringify_keys)
674
+ hash = where_values_hash
675
+ hash.delete(klass.inheritance_column) if klass.finder_needs_type_condition?
676
+ create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
677
+ hash
675
678
  end
676
679
 
677
680
  # Returns true if relation needs eager loading.
@@ -134,7 +134,7 @@ module ActiveRecord
134
134
  relation.select_values = [ klass.primary_key || table[Arel.star] ]
135
135
  end
136
136
  # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
137
- relation.order_values = []
137
+ relation.order_values = [] if group_values.empty?
138
138
  end
139
139
 
140
140
  relation.calculate(operation, column_name)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "mutex_m"
4
+ require "active_support/core_ext/module/delegation"
4
5
 
5
6
  module ActiveRecord
6
7
  module Delegation # :nodoc:
@@ -59,7 +60,7 @@ module ActiveRecord
59
60
  synchronize do
60
61
  return if method_defined?(method)
61
62
 
62
- if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method)
63
+ if /\A[a-zA-Z_]\w*[!?]?\z/.match?(method) && !DELEGATION_RESERVED_METHOD_NAMES.include?(method.to_s)
63
64
  definition = RUBY_VERSION >= "2.7" ? "..." : "*args, &block"
64
65
  module_eval <<-RUBY, __FILE__, __LINE__ + 1
65
66
  def #{method}(#{definition})
@@ -371,7 +371,7 @@ module ActiveRecord
371
371
 
372
372
  def apply_join_dependency(eager_loading: group_values.empty?)
373
373
  join_dependency = construct_join_dependency(
374
- eager_load_values + includes_values, Arel::Nodes::OuterJoin
374
+ eager_load_values | includes_values, Arel::Nodes::OuterJoin
375
375
  )
376
376
  relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
377
377
 
@@ -135,11 +135,16 @@ module ActiveRecord
135
135
  if other.klass == relation.klass
136
136
  relation.left_outer_joins!(*other.left_outer_joins_values)
137
137
  else
138
- associations = other.left_outer_joins_values
138
+ associations, others = other.left_outer_joins_values.partition do |join|
139
+ case join
140
+ when Hash, Symbol, Array; true
141
+ end
142
+ end
143
+
139
144
  join_dependency = other.construct_join_dependency(
140
145
  associations, Arel::Nodes::OuterJoin
141
146
  )
142
- relation.joins!(join_dependency)
147
+ relation.left_outer_joins!(join_dependency, *others)
143
148
  end
144
149
  end
145
150
 
@@ -331,7 +331,7 @@ module ActiveRecord
331
331
  def group!(*args) # :nodoc:
332
332
  args.flatten!
333
333
 
334
- self.group_values |= args
334
+ self.group_values += args
335
335
  self
336
336
  end
337
337
 
@@ -1094,12 +1094,14 @@ module ActiveRecord
1094
1094
  end
1095
1095
  end
1096
1096
 
1097
- def select_association_list(associations)
1097
+ def select_association_list(associations, stashed_joins = nil)
1098
1098
  result = []
1099
1099
  associations.each do |association|
1100
1100
  case association
1101
1101
  when Hash, Symbol, Array
1102
1102
  result << association
1103
+ when ActiveRecord::Associations::JoinDependency
1104
+ stashed_joins&.<< association
1103
1105
  else
1104
1106
  yield if block_given?
1105
1107
  end
@@ -1107,28 +1109,32 @@ module ActiveRecord
1107
1109
  result
1108
1110
  end
1109
1111
 
1110
- def valid_association_list(associations)
1111
- select_association_list(associations) do
1112
+ def valid_association_list(associations, stashed_joins)
1113
+ select_association_list(associations, stashed_joins) do
1112
1114
  raise ArgumentError, "only Hash, Symbol and Array are allowed"
1113
1115
  end
1114
1116
  end
1115
1117
 
1116
1118
  def build_left_outer_joins(manager, outer_joins, aliases)
1117
1119
  buckets = Hash.new { |h, k| h[k] = [] }
1118
- buckets[:association_join] = valid_association_list(outer_joins)
1120
+ buckets[:association_join] = valid_association_list(outer_joins, buckets[:stashed_join])
1119
1121
  build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
1120
1122
  end
1121
1123
 
1124
+ class ::Arel::Nodes::LeadingJoin < Arel::Nodes::InnerJoin # :nodoc:
1125
+ end
1126
+
1122
1127
  def build_joins(manager, joins, aliases)
1123
1128
  buckets = Hash.new { |h, k| h[k] = [] }
1124
1129
 
1125
1130
  unless left_outer_joins_values.empty?
1126
- left_joins = valid_association_list(left_outer_joins_values.flatten)
1127
- buckets[:stashed_join] << construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
1131
+ stashed_left_joins = []
1132
+ left_joins = valid_association_list(left_outer_joins_values.flatten, stashed_left_joins)
1133
+ stashed_left_joins.unshift construct_join_dependency(left_joins, Arel::Nodes::OuterJoin)
1128
1134
  end
1129
1135
 
1130
1136
  if joins.last.is_a?(ActiveRecord::Associations::JoinDependency)
1131
- buckets[:stashed_join] << joins.pop if joins.last.base_klass == klass
1137
+ stashed_eager_load = joins.pop if joins.last.base_klass == klass
1132
1138
  end
1133
1139
 
1134
1140
  joins.map! do |join|
@@ -1141,7 +1147,7 @@ module ActiveRecord
1141
1147
 
1142
1148
  while joins.first.is_a?(Arel::Nodes::Join)
1143
1149
  join_node = joins.shift
1144
- if join_node.is_a?(Arel::Nodes::StringJoin) && !buckets[:stashed_join].empty?
1150
+ if !join_node.is_a?(Arel::Nodes::LeadingJoin) && (stashed_eager_load || stashed_left_joins)
1145
1151
  buckets[:join_node] << join_node
1146
1152
  else
1147
1153
  buckets[:leading_join] << join_node
@@ -1161,6 +1167,9 @@ module ActiveRecord
1161
1167
  end
1162
1168
  end
1163
1169
 
1170
+ buckets[:stashed_join].concat stashed_left_joins if stashed_left_joins
1171
+ buckets[:stashed_join] << stashed_eager_load if stashed_eager_load
1172
+
1164
1173
  build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
1165
1174
  end
1166
1175
 
@@ -1356,12 +1365,15 @@ module ActiveRecord
1356
1365
  end
1357
1366
  end
1358
1367
 
1359
- STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
1368
+ STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references, :annotate, :optimizer_hints]
1360
1369
  def structurally_incompatible_values_for_or(other)
1361
1370
  values = other.values
1362
1371
  STRUCTURAL_OR_METHODS.reject do |method|
1363
1372
  default = DEFAULT_VALUES[method]
1364
- @values.fetch(method, default) == values.fetch(method, default)
1373
+ v1, v2 = @values.fetch(method, default), values.fetch(method, default)
1374
+ v1 = v1.uniq if v1.is_a?(Array)
1375
+ v2 = v2.uniq if v2.is_a?(Array)
1376
+ v1 == v2
1365
1377
  end
1366
1378
  end
1367
1379
 
@@ -200,11 +200,16 @@ module ActiveRecord
200
200
  scope
201
201
  end
202
202
  end
203
+ singleton_class.send(:ruby2_keywords, name) if respond_to?(:ruby2_keywords, true)
203
204
 
204
205
  generate_relation_method(name)
205
206
  end
206
207
 
207
208
  private
209
+ def singleton_method_added(name)
210
+ generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
211
+ end
212
+
208
213
  def valid_scope_name?(name)
209
214
  if respond_to?(name, true) && logger
210
215
  logger.warn "Creating scope :#{name}. " \
@@ -112,6 +112,8 @@ module ActiveRecord
112
112
 
113
113
  # Load fixtures once and begin transaction.
114
114
  if run_in_transaction?
115
+ @saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
116
+
115
117
  if @@already_loaded_fixtures[self.class]
116
118
  @loaded_fixtures = @@already_loaded_fixtures[self.class]
117
119
  else
@@ -166,6 +168,7 @@ module ActiveRecord
166
168
  connection.pool.lock_thread = false
167
169
  end
168
170
  @fixture_connections.clear
171
+ teardown_shared_connection_pool
169
172
  else
170
173
  ActiveRecord::FixtureSet.reset_cache
171
174
  end
@@ -187,7 +190,7 @@ module ActiveRecord
187
190
  # need to share a connection pool so that the reading connection
188
191
  # can see data in the open transaction on the writing connection.
189
192
  def setup_shared_connection_pool
190
- writing_handler = ActiveRecord::Base.connection_handler
193
+ writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
191
194
 
192
195
  ActiveRecord::Base.connection_handlers.values.each do |handler|
193
196
  if handler != writing_handler
@@ -195,12 +198,27 @@ module ActiveRecord
195
198
  name = pool.spec.name
196
199
  writing_connection = writing_handler.retrieve_connection_pool(name)
197
200
  return unless writing_connection
201
+
202
+ reading_connection = handler.send(:owner_to_pool)[name]
203
+ next if reading_connection == writing_connection
204
+
205
+ @saved_pool_configs[handler][name] = reading_connection
198
206
  handler.send(:owner_to_pool)[name] = writing_connection
199
207
  end
200
208
  end
201
209
  end
202
210
  end
203
211
 
212
+ def teardown_shared_connection_pool
213
+ @saved_pool_configs.each_pair do |handler, pools|
214
+ pools.each_pair do |name, pool|
215
+ handler.send(:owner_to_pool)[name] = pool
216
+ end
217
+ end
218
+
219
+ @saved_pool_configs.clear
220
+ end
221
+
204
222
  def load_fixtures(config)
205
223
  fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
206
224
  Hash[fixtures.map { |f| [f.name, f] }]
@@ -16,6 +16,16 @@ module ActiveRecord
16
16
  value
17
17
  end
18
18
  end
19
+
20
+ private
21
+ def cast_value(value)
22
+ case value = super
23
+ when Value
24
+ value.__getobj__
25
+ else
26
+ value
27
+ end
28
+ end
19
29
  end
20
30
  end
21
31
  end
@@ -5,7 +5,7 @@ module ActiveRecord
5
5
  class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
6
6
  def validate_each(record, attribute, value)
7
7
  if Array(value).reject { |r| valid_object?(r) }.any?
8
- record.errors.add(attribute, :invalid, **options.merge(value: value))
8
+ record.errors.add(attribute, :invalid, options.merge(value: value))
9
9
  end
10
10
  end
11
11
 
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.0.3.7
4
+ version: 6.0.4
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: 2021-05-05 00:00:00.000000000 Z
11
+ date: 2021-06-15 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.0.3.7
19
+ version: 6.0.4
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.0.3.7
26
+ version: 6.0.4
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.0.3.7
33
+ version: 6.0.4
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.0.3.7
40
+ version: 6.0.4
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.
@@ -391,11 +391,11 @@ licenses:
391
391
  - MIT
392
392
  metadata:
393
393
  bug_tracker_uri: https://github.com/rails/rails/issues
394
- changelog_uri: https://github.com/rails/rails/blob/v6.0.3.7/activerecord/CHANGELOG.md
395
- documentation_uri: https://api.rubyonrails.org/v6.0.3.7/
394
+ changelog_uri: https://github.com/rails/rails/blob/v6.0.4/activerecord/CHANGELOG.md
395
+ documentation_uri: https://api.rubyonrails.org/v6.0.4/
396
396
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
397
- source_code_uri: https://github.com/rails/rails/tree/v6.0.3.7/activerecord
398
- post_install_message:
397
+ source_code_uri: https://github.com/rails/rails/tree/v6.0.4/activerecord
398
+ post_install_message:
399
399
  rdoc_options:
400
400
  - "--main"
401
401
  - README.rdoc
@@ -413,7 +413,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
413
413
  version: '0'
414
414
  requirements: []
415
415
  rubygems_version: 3.1.2
416
- signing_key:
416
+ signing_key:
417
417
  specification_version: 4
418
418
  summary: Object-relational mapper framework (part of Rails).
419
419
  test_files: []