activerecord 6.0.0.beta3 → 6.0.0.rc1

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +286 -6
  3. data/README.rdoc +3 -1
  4. data/lib/active_record.rb +0 -1
  5. data/lib/active_record/associations.rb +3 -2
  6. data/lib/active_record/associations/association.rb +1 -1
  7. data/lib/active_record/associations/builder/association.rb +14 -18
  8. data/lib/active_record/associations/builder/belongs_to.rb +5 -2
  9. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  10. data/lib/active_record/associations/builder/has_many.rb +2 -0
  11. data/lib/active_record/associations/builder/has_one.rb +35 -1
  12. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  13. data/lib/active_record/associations/collection_proxy.rb +1 -1
  14. data/lib/active_record/associations/has_many_through_association.rb +4 -11
  15. data/lib/active_record/associations/preloader.rb +11 -6
  16. data/lib/active_record/associations/preloader/association.rb +32 -30
  17. data/lib/active_record/associations/preloader/through_association.rb +48 -28
  18. data/lib/active_record/attribute_methods.rb +4 -3
  19. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
  20. data/lib/active_record/attribute_methods/dirty.rb +42 -14
  21. data/lib/active_record/attribute_methods/primary_key.rb +7 -15
  22. data/lib/active_record/attribute_methods/query.rb +2 -3
  23. data/lib/active_record/attribute_methods/read.rb +3 -9
  24. data/lib/active_record/attribute_methods/write.rb +6 -12
  25. data/lib/active_record/attributes.rb +13 -0
  26. data/lib/active_record/autosave_association.rb +13 -3
  27. data/lib/active_record/base.rb +0 -1
  28. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -0
  29. data/lib/active_record/connection_adapters/abstract/database_limits.rb +8 -4
  30. data/lib/active_record/connection_adapters/abstract/database_statements.rb +84 -61
  31. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
  32. data/lib/active_record/connection_adapters/abstract/quoting.rb +10 -6
  33. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +4 -7
  34. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +70 -14
  35. data/lib/active_record/connection_adapters/abstract_adapter.rb +56 -11
  36. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -69
  37. data/lib/active_record/connection_adapters/column.rb +17 -13
  38. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -7
  39. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +4 -4
  40. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +9 -6
  41. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  42. data/lib/active_record/connection_adapters/mysql2_adapter.rb +6 -2
  43. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -30
  44. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +5 -1
  45. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +34 -38
  46. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +23 -27
  47. data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -27
  48. data/lib/active_record/connection_adapters/schema_cache.rb +32 -14
  49. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  50. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  51. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +2 -2
  52. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +50 -112
  53. data/lib/active_record/connection_handling.rb +17 -10
  54. data/lib/active_record/core.rb +15 -20
  55. data/lib/active_record/database_configurations.rb +14 -14
  56. data/lib/active_record/database_configurations/hash_config.rb +11 -11
  57. data/lib/active_record/database_configurations/url_config.rb +12 -12
  58. data/lib/active_record/dynamic_matchers.rb +1 -1
  59. data/lib/active_record/enum.rb +6 -0
  60. data/lib/active_record/errors.rb +1 -1
  61. data/lib/active_record/gem_version.rb +1 -1
  62. data/lib/active_record/insert_all.rb +180 -0
  63. data/lib/active_record/integration.rb +13 -1
  64. data/lib/active_record/internal_metadata.rb +5 -1
  65. data/lib/active_record/locking/optimistic.rb +3 -4
  66. data/lib/active_record/log_subscriber.rb +1 -1
  67. data/lib/active_record/migration.rb +25 -18
  68. data/lib/active_record/migration/command_recorder.rb +28 -14
  69. data/lib/active_record/migration/compatibility.rb +10 -0
  70. data/lib/active_record/persistence.rb +206 -13
  71. data/lib/active_record/querying.rb +17 -12
  72. data/lib/active_record/railties/databases.rake +68 -6
  73. data/lib/active_record/reflection.rb +2 -2
  74. data/lib/active_record/relation.rb +98 -20
  75. data/lib/active_record/relation/calculations.rb +39 -39
  76. data/lib/active_record/relation/delegation.rb +22 -30
  77. data/lib/active_record/relation/finder_methods.rb +3 -9
  78. data/lib/active_record/relation/merger.rb +7 -16
  79. data/lib/active_record/relation/query_methods.rb +153 -38
  80. data/lib/active_record/relation/where_clause.rb +9 -5
  81. data/lib/active_record/sanitization.rb +3 -2
  82. data/lib/active_record/schema_dumper.rb +5 -0
  83. data/lib/active_record/schema_migration.rb +1 -1
  84. data/lib/active_record/scoping/default.rb +6 -7
  85. data/lib/active_record/scoping/named.rb +1 -1
  86. data/lib/active_record/statement_cache.rb +2 -2
  87. data/lib/active_record/store.rb +48 -0
  88. data/lib/active_record/table_metadata.rb +3 -3
  89. data/lib/active_record/tasks/database_tasks.rb +36 -1
  90. data/lib/active_record/touch_later.rb +2 -2
  91. data/lib/active_record/transactions.rb +52 -41
  92. data/lib/active_record/validations/uniqueness.rb +3 -5
  93. data/lib/arel/insert_manager.rb +3 -3
  94. data/lib/arel/nodes.rb +2 -1
  95. data/lib/arel/nodes/comment.rb +29 -0
  96. data/lib/arel/nodes/select_core.rb +16 -12
  97. data/lib/arel/nodes/unary.rb +1 -0
  98. data/lib/arel/nodes/values_list.rb +2 -17
  99. data/lib/arel/select_manager.rb +10 -10
  100. data/lib/arel/visitors/depth_first.rb +6 -1
  101. data/lib/arel/visitors/dot.rb +7 -2
  102. data/lib/arel/visitors/ibm_db.rb +13 -0
  103. data/lib/arel/visitors/informix.rb +6 -0
  104. data/lib/arel/visitors/mssql.rb +15 -1
  105. data/lib/arel/visitors/oracle12.rb +4 -5
  106. data/lib/arel/visitors/postgresql.rb +4 -10
  107. data/lib/arel/visitors/to_sql.rb +87 -108
  108. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  109. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  110. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  111. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  112. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  113. metadata +12 -11
  114. data/lib/active_record/collection_cache_key.rb +0 -53
  115. data/lib/arel/nodes/values.rb +0 -16
@@ -74,11 +74,11 @@ module ActiveRecord::Associations::Builder # :nodoc:
74
74
 
75
75
  def self.add_touch_callbacks(model, reflection)
76
76
  foreign_key = reflection.foreign_key
77
- n = reflection.name
77
+ name = reflection.name
78
78
  touch = reflection.options[:touch]
79
79
 
80
80
  callback = lambda { |changes_method| lambda { |record|
81
- BelongsTo.touch_record(record, record.send(changes_method), foreign_key, n, touch, belongs_to_touch_method)
81
+ BelongsTo.touch_record(record, record.send(changes_method), foreign_key, name, touch, belongs_to_touch_method)
82
82
  }}
83
83
 
84
84
  if reflection.counter_cache_column
@@ -123,5 +123,8 @@ module ActiveRecord::Associations::Builder # :nodoc:
123
123
  model.validates_presence_of reflection.name, message: :required
124
124
  end
125
125
  end
126
+
127
+ private_class_method :macro, :valid_options, :valid_dependent_options, :define_callbacks, :define_validations,
128
+ :add_counter_cache_callbacks, :add_touch_callbacks, :add_default_callbacks, :add_destroy_callbacks
126
129
  end
127
130
  end
@@ -20,10 +20,10 @@ module ActiveRecord::Associations::Builder # :nodoc:
20
20
  }
21
21
  end
22
22
 
23
- def self.define_extensions(model, name)
23
+ def self.define_extensions(model, name, &block)
24
24
  if block_given?
25
25
  extension_module_name = "#{model.name.demodulize}#{name.to_s.camelize}AssociationExtension"
26
- extension = Module.new(&Proc.new)
26
+ extension = Module.new(&block)
27
27
  model.module_parent.const_set(extension_module_name, extension)
28
28
  end
29
29
  end
@@ -67,16 +67,6 @@ module ActiveRecord::Associations::Builder # :nodoc:
67
67
  CODE
68
68
  end
69
69
 
70
- def self.wrap_scope(scope, mod)
71
- if scope
72
- if scope.arity > 0
73
- proc { |owner| instance_exec(owner, &scope).extending(mod) }
74
- else
75
- proc { instance_exec(&scope).extending(mod) }
76
- end
77
- else
78
- proc { extending(mod) }
79
- end
80
- end
70
+ private_class_method :valid_options, :define_callback, :define_extensions, :define_readers, :define_writers
81
71
  end
82
72
  end
@@ -13,5 +13,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
13
13
  def self.valid_dependent_options
14
14
  [:destroy, :delete_all, :nullify, :restrict_with_error, :restrict_with_exception]
15
15
  end
16
+
17
+ private_class_method :macro, :valid_options, :valid_dependent_options
16
18
  end
17
19
  end
@@ -7,7 +7,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
7
7
  end
8
8
 
9
9
  def self.valid_options(options)
10
- valid = super + [:as]
10
+ valid = super + [:as, :touch]
11
11
  valid += [:through, :source, :source_type] if options[:through]
12
12
  valid
13
13
  end
@@ -16,6 +16,11 @@ module ActiveRecord::Associations::Builder # :nodoc:
16
16
  [:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception]
17
17
  end
18
18
 
19
+ def self.define_callbacks(model, reflection)
20
+ super
21
+ add_touch_callbacks(model, reflection) if reflection.options[:touch]
22
+ end
23
+
19
24
  def self.add_destroy_callbacks(model, reflection)
20
25
  super unless reflection.options[:through]
21
26
  end
@@ -26,5 +31,34 @@ module ActiveRecord::Associations::Builder # :nodoc:
26
31
  model.validates_presence_of reflection.name, message: :required
27
32
  end
28
33
  end
34
+
35
+ def self.touch_record(o, name, touch)
36
+ record = o.send name
37
+
38
+ return unless record && record.persisted?
39
+
40
+ if touch != true
41
+ record.touch(touch)
42
+ else
43
+ record.touch
44
+ end
45
+ end
46
+
47
+ def self.add_touch_callbacks(model, reflection)
48
+ name = reflection.name
49
+ touch = reflection.options[:touch]
50
+
51
+ callback = lambda { |record|
52
+ HasOne.touch_record(record, name, touch)
53
+ }
54
+
55
+ model.after_create callback, if: :saved_changes?
56
+ model.after_update callback, if: :saved_changes?
57
+ model.after_destroy callback
58
+ model.after_touch callback
59
+ end
60
+
61
+ private_class_method :macro, :valid_options, :valid_dependent_options, :add_destroy_callbacks,
62
+ :define_callbacks, :define_validations, :add_touch_callbacks
29
63
  end
30
64
  end
@@ -38,5 +38,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
38
38
  end
39
39
  CODE
40
40
  end
41
+
42
+ private_class_method :valid_options, :define_accessors, :define_constructors
41
43
  end
42
44
  end
@@ -1002,7 +1002,7 @@ module ActiveRecord
1002
1002
  end
1003
1003
 
1004
1004
  # Adds one or more +records+ to the collection by setting their foreign keys
1005
- # to the association's primary key. Since +<<+ flattens its argument list and
1005
+ # to the association's primary key. Since <tt><<</tt> flattens its argument list and
1006
1006
  # inserts each record, +push+ and +concat+ behave identically. Returns +self+
1007
1007
  # so several appends may be chained together.
1008
1008
  #
@@ -57,21 +57,14 @@ module ActiveRecord
57
57
  @through_records[record.object_id] ||= begin
58
58
  ensure_mutable
59
59
 
60
- through_record = through_association.build(*options_for_through_record)
61
- through_record.send("#{source_reflection.name}=", record)
60
+ attributes = through_scope_attributes
61
+ attributes[source_reflection.name] = record
62
+ attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
62
63
 
63
- if options[:source_type]
64
- through_record.send("#{source_reflection.foreign_type}=", options[:source_type])
65
- end
66
-
67
- through_record
64
+ through_association.build(attributes)
68
65
  end
69
66
  end
70
67
 
71
- def options_for_through_record
72
- [through_scope_attributes]
73
- end
74
-
75
68
  def through_scope_attributes
76
69
  scope.where_values_hash(through_association.reflection.name.to_s).
77
70
  except!(through_association.reflection.foreign_key,
@@ -143,16 +143,13 @@ module ActiveRecord
143
143
 
144
144
  def preloaders_for_reflection(reflection, records, scope)
145
145
  records.group_by { |record| record.association(reflection.name).klass }.map do |rhs_klass, rs|
146
- loader = preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope)
147
- loader.run self
148
- loader
146
+ preloader_for(reflection, rs).new(rhs_klass, rs, reflection, scope).run
149
147
  end
150
148
  end
151
149
 
152
150
  def grouped_records(association, records, polymorphic_parent)
153
151
  h = {}
154
152
  records.each do |record|
155
- next unless record
156
153
  reflection = record.class._reflect_on_association(association)
157
154
  next if polymorphic_parent && !reflection || !record.association(association).klass
158
155
  (h[reflection] ||= []) << record
@@ -166,10 +163,18 @@ module ActiveRecord
166
163
  @reflection = reflection
167
164
  end
168
165
 
169
- def run(preloader); end
166
+ def run
167
+ self
168
+ end
170
169
 
171
170
  def preloaded_records
172
- owners.flat_map { |owner| owner.association(reflection.name).target }
171
+ @preloaded_records ||= records_by_owner.flat_map(&:last)
172
+ end
173
+
174
+ def records_by_owner
175
+ @records_by_owner ||= owners.each_with_object({}) do |owner, result|
176
+ result[owner] = Array(owner.association(reflection.name).target)
177
+ end
173
178
  end
174
179
 
175
180
  private
@@ -4,29 +4,41 @@ module ActiveRecord
4
4
  module Associations
5
5
  class Preloader
6
6
  class Association #:nodoc:
7
- attr_reader :preloaded_records
8
-
9
7
  def initialize(klass, owners, reflection, preload_scope)
10
8
  @klass = klass
11
9
  @owners = owners
12
10
  @reflection = reflection
13
11
  @preload_scope = preload_scope
14
12
  @model = owners.first && owners.first.class
15
- @preloaded_records = []
16
13
  end
17
14
 
18
- def run(preloader)
19
- records = load_records do |record|
20
- owner = owners_by_key[convert_key(record[association_key_name])]
21
- association = owner.association(reflection.name)
22
- association.set_inverse_instance(record)
15
+ def run
16
+ if !preload_scope || preload_scope.empty_scope?
17
+ owners.each do |owner|
18
+ associate_records_to_owner(owner, records_by_owner[owner] || [])
19
+ end
20
+ else
21
+ # Custom preload scope is used and
22
+ # the association can not be marked as loaded
23
+ # Loading into a Hash instead
24
+ records_by_owner
23
25
  end
26
+ self
27
+ end
24
28
 
25
- owners.each do |owner|
26
- associate_records_to_owner(owner, records[convert_key(owner[owner_key_name])] || [])
29
+ def records_by_owner
30
+ @records_by_owner ||= preloaded_records.each_with_object({}) do |record, result|
31
+ owners_by_key[convert_key(record[association_key_name])].each do |owner|
32
+ (result[owner] ||= []) << record
33
+ end
27
34
  end
28
35
  end
29
36
 
37
+ def preloaded_records
38
+ return @preloaded_records if defined?(@preloaded_records)
39
+ @preloaded_records = owner_keys.empty? ? [] : records_for(owner_keys)
40
+ end
41
+
30
42
  private
31
43
  attr_reader :owners, :reflection, :preload_scope, :model, :klass
32
44
 
@@ -54,13 +66,10 @@ module ActiveRecord
54
66
  end
55
67
 
56
68
  def owners_by_key
57
- unless defined?(@owners_by_key)
58
- @owners_by_key = owners.each_with_object({}) do |owner, h|
59
- key = convert_key(owner[owner_key_name])
60
- h[key] = owner if key
61
- end
69
+ @owners_by_key ||= owners.each_with_object({}) do |owner, result|
70
+ key = convert_key(owner[owner_key_name])
71
+ (result[key] ||= []) << owner if key
62
72
  end
63
- @owners_by_key
64
73
  end
65
74
 
66
75
  def key_conversion_required?
@@ -87,23 +96,16 @@ module ActiveRecord
87
96
  @model.type_for_attribute(owner_key_name).type
88
97
  end
89
98
 
90
- def load_records(&block)
91
- return {} if owner_keys.empty?
92
- # Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
93
- # Make several smaller queries if necessary or make one query if the adapter supports it
94
- slices = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
95
- @preloaded_records = slices.flat_map do |slice|
96
- records_for(slice, &block)
97
- end
98
- @preloaded_records.group_by do |record|
99
- convert_key(record[association_key_name])
99
+ def records_for(ids)
100
+ scope.where(association_key_name => ids).load do |record|
101
+ # Processing only the first owner
102
+ # because the record is modified but not an owner
103
+ owner = owners_by_key[convert_key(record[association_key_name])].first
104
+ association = owner.association(reflection.name)
105
+ association.set_inverse_instance(record)
100
106
  end
101
107
  end
102
108
 
103
- def records_for(ids, &block)
104
- scope.where(association_key_name => ids).load(&block)
105
- end
106
-
107
109
  def scope
108
110
  @scope ||= build_scope
109
111
  end
@@ -4,41 +4,57 @@ module ActiveRecord
4
4
  module Associations
5
5
  class Preloader
6
6
  class ThroughAssociation < Association # :nodoc:
7
- def run(preloader)
8
- already_loaded = owners.first.association(through_reflection.name).loaded?
9
- through_scope = through_scope()
10
- through_preloaders = preloader.preload(owners, through_reflection.name, through_scope)
11
- middle_records = through_preloaders.flat_map(&:preloaded_records)
12
- preloaders = preloader.preload(middle_records, source_reflection.name, scope)
13
- @preloaded_records = preloaders.flat_map(&:preloaded_records)
14
-
15
- owners.each do |owner|
16
- through_records = Array(owner.association(through_reflection.name).target)
17
- if already_loaded
7
+ PRELOADER = ActiveRecord::Associations::Preloader.new
8
+
9
+ def initialize(*)
10
+ super
11
+ @already_loaded = owners.first.association(through_reflection.name).loaded?
12
+ end
13
+
14
+ def preloaded_records
15
+ @preloaded_records ||= source_preloaders.flat_map(&:preloaded_records)
16
+ end
17
+
18
+ def records_by_owner
19
+ return @records_by_owner if defined?(@records_by_owner)
20
+ source_records_by_owner = source_preloaders.map(&:records_by_owner).reduce(:merge)
21
+ through_records_by_owner = through_preloaders.map(&:records_by_owner).reduce(:merge)
22
+
23
+ @records_by_owner = owners.each_with_object({}) do |owner, result|
24
+ through_records = through_records_by_owner[owner] || []
25
+
26
+ if @already_loaded
18
27
  if source_type = reflection.options[:source_type]
19
28
  through_records = through_records.select do |record|
20
29
  record[reflection.foreign_type] == source_type
21
30
  end
22
31
  end
23
- else
24
- owner.association(through_reflection.name).reset if through_scope
25
- end
26
- result = through_records.flat_map do |record|
27
- record.association(source_reflection.name).target
28
32
  end
29
- result.compact!
30
- result.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
31
- result.uniq! if scope.distinct_value
32
- associate_records_to_owner(owner, result)
33
- end
34
- unless scope.empty_scope?
35
- middle_records.each do |owner|
36
- owner.association(source_reflection.name).reset
33
+
34
+ records = through_records.flat_map do |record|
35
+ source_records_by_owner[record]
37
36
  end
37
+
38
+ records.compact!
39
+ records.sort_by! { |rhs| preload_index[rhs] } if scope.order_values.any?
40
+ records.uniq! if scope.distinct_value
41
+ result[owner] = records
38
42
  end
39
43
  end
40
44
 
41
45
  private
46
+ def source_preloaders
47
+ @source_preloaders ||= PRELOADER.preload(middle_records, source_reflection.name, scope)
48
+ end
49
+
50
+ def middle_records
51
+ through_preloaders.flat_map(&:preloaded_records)
52
+ end
53
+
54
+ def through_preloaders
55
+ @through_preloaders ||= PRELOADER.preload(owners, through_reflection.name, through_scope)
56
+ end
57
+
42
58
  def through_reflection
43
59
  reflection.through_reflection
44
60
  end
@@ -48,8 +64,8 @@ module ActiveRecord
48
64
  end
49
65
 
50
66
  def preload_index
51
- @preload_index ||= @preloaded_records.each_with_object({}).with_index do |(id, result), index|
52
- result[id] = index
67
+ @preload_index ||= preloaded_records.each_with_object({}).with_index do |(record, result), index|
68
+ result[record] = index
53
69
  end
54
70
  end
55
71
 
@@ -57,11 +73,15 @@ module ActiveRecord
57
73
  scope = through_reflection.klass.unscoped
58
74
  options = reflection.options
59
75
 
76
+ values = reflection_scope.values
77
+ if annotations = values[:annotate]
78
+ scope.annotate!(*annotations)
79
+ end
80
+
60
81
  if options[:source_type]
61
82
  scope.where! reflection.foreign_type => options[:source_type]
62
83
  elsif !reflection_scope.where_clause.empty?
63
84
  scope.where_clause = reflection_scope.where_clause
64
- values = reflection_scope.values
65
85
 
66
86
  if includes = values[:includes]
67
87
  scope.includes!(source_reflection.name => includes)
@@ -88,7 +108,7 @@ module ActiveRecord
88
108
  end
89
109
  end
90
110
 
91
- scope unless scope.empty_scope?
111
+ scope
92
112
  end
93
113
  end
94
114
  end
@@ -35,7 +35,8 @@ module ActiveRecord
35
35
  end
36
36
 
37
37
  def initialize_generated_modules # :nodoc:
38
- @generated_attribute_methods = GeneratedAttributeMethods.new
38
+ @generated_attribute_methods = const_set(:GeneratedAttributeMethods, GeneratedAttributeMethods.new)
39
+ private_constant :GeneratedAttributeMethods
39
40
  @attribute_methods_generated = false
40
41
  include @generated_attribute_methods
41
42
 
@@ -196,7 +197,7 @@ module ActiveRecord
196
197
  "Dangerous query method (method whose arguments are used as raw " \
197
198
  "SQL) called with non-attribute argument(s): " \
198
199
  "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
199
- "arguments will be disallowed in Rails 6.0. This method should " \
200
+ "arguments will be disallowed in Rails 6.1. This method should " \
200
201
  "not be called with user-provided values, such as request " \
201
202
  "parameters or model attributes. Known-safe values can be passed " \
202
203
  "by wrapping them in Arel.sql()."
@@ -464,7 +465,7 @@ module ActiveRecord
464
465
  end
465
466
 
466
467
  def pk_attribute?(name)
467
- name == self.class.primary_key
468
+ name == @primary_key
468
469
  end
469
470
  end
470
471
  end
@@ -46,6 +46,7 @@ module ActiveRecord
46
46
  # task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
47
47
  # task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
48
48
  def read_attribute_before_type_cast(attr_name)
49
+ sync_with_transaction_state if @transaction_state&.finalized?
49
50
  @attributes[attr_name.to_s].value_before_type_cast
50
51
  end
51
52
 
@@ -60,17 +61,19 @@ module ActiveRecord
60
61
  # task.attributes_before_type_cast
61
62
  # # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil}
62
63
  def attributes_before_type_cast
64
+ sync_with_transaction_state if @transaction_state&.finalized?
63
65
  @attributes.values_before_type_cast
64
66
  end
65
67
 
66
68
  private
67
69
 
68
- # Handle *_before_type_cast for method_missing.
70
+ # Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
69
71
  def attribute_before_type_cast(attribute_name)
70
72
  read_attribute_before_type_cast(attribute_name)
71
73
  end
72
74
 
73
75
  def attribute_came_from_user?(attribute_name)
76
+ sync_with_transaction_state if @transaction_state&.finalized?
74
77
  @attributes[attribute_name].came_from_user?
75
78
  end
76
79
  end