mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Make a deep copy of the _default_attributes in column_defaults
When column_defaults is called it calls `value` on each instance of Attribute inside the _default_attributes set. Since value is memoized in the Attribute instance and that Attribute instance is shared across all instances of a model the next call to the default value will be memozied not running the proc defined by the user. Fixes #33031.
This commit is contained in:
parent
e184d1a94e
commit
a0482d3911
2 changed files with 15 additions and 1 deletions
|
@ -375,7 +375,7 @@ module ActiveRecord
|
|||
# default values when instantiating the Active Record object for this table.
|
||||
def column_defaults
|
||||
load_schema
|
||||
@column_defaults ||= _default_attributes.to_hash
|
||||
@column_defaults ||= _default_attributes.deep_dup.to_hash
|
||||
end
|
||||
|
||||
def _default_attributes # :nodoc:
|
||||
|
|
|
@ -148,6 +148,20 @@ module ActiveRecord
|
|||
assert_equal 2, klass.new.counter
|
||||
end
|
||||
|
||||
test "procs for default values are evaluated even after column_defaults is called" do
|
||||
klass = Class.new(OverloadedType) do
|
||||
@@counter = 0
|
||||
attribute :counter, :integer, default: -> { @@counter += 1 }
|
||||
end
|
||||
|
||||
assert_equal 1, klass.new.counter
|
||||
|
||||
# column_defaults will increment the counter since the proc is called
|
||||
klass.column_defaults
|
||||
|
||||
assert_equal 3, klass.new.counter
|
||||
end
|
||||
|
||||
test "procs are memoized before type casting" do
|
||||
klass = Class.new(OverloadedType) do
|
||||
@@counter = 0
|
||||
|
|
Loading…
Reference in a new issue