mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Keep column defaults in type cast form
The contract of `_field_changed?` assumes that the old value is always type cast. That is not the case for the value in `Column#default` as things are today. It appears there are other public methods that assume that `Column#default` is type cast, as well. The reason for this change originally was because the value gets put into `@raw_attributes` in initialize. This reverts to the old behavior on `Column`, and updates `initialize` to make sure that the values are in the right format.
This commit is contained in:
parent
098bb63ae4
commit
ed559d4b00
5 changed files with 40 additions and 2 deletions
|
@ -52,7 +52,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def extract_default(default)
|
||||
type_cast_for_write(type_cast(default))
|
||||
type_cast(default)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -249,7 +249,7 @@ module ActiveRecord
|
|||
# # Instantiates a single new object
|
||||
# User.new(first_name: 'Jamie')
|
||||
def initialize(attributes = nil, options = {})
|
||||
defaults = self.class.column_defaults.dup
|
||||
defaults = self.class.raw_column_defaults.dup
|
||||
defaults.each { |k, v| defaults[k] = v.dup if v.duplicable? }
|
||||
|
||||
@raw_attributes = defaults
|
||||
|
|
|
@ -241,6 +241,14 @@ module ActiveRecord
|
|||
@column_defaults ||= Hash[columns.map { |c| [c.name, c.default] }]
|
||||
end
|
||||
|
||||
# Returns a hash where the keys are the column names and the values
|
||||
# are the default values suitable for use in `@raw_attriubtes`
|
||||
def raw_column_defaults # :nodoc:
|
||||
@raw_column_defauts ||= Hash[column_defaults.map { |name, default|
|
||||
[name, columns_hash[name].type_cast_for_write(default)]
|
||||
}]
|
||||
end
|
||||
|
||||
# Returns an array of column names as strings.
|
||||
def column_names
|
||||
@column_names ||= columns.map { |column| column.name }
|
||||
|
@ -285,6 +293,7 @@ module ActiveRecord
|
|||
|
||||
@arel_engine = nil
|
||||
@column_defaults = nil
|
||||
@raw_column_defauts = nil
|
||||
@column_names = nil
|
||||
@column_types = nil
|
||||
@content_columns = nil
|
||||
|
|
|
@ -113,6 +113,7 @@ module ActiveRecord
|
|||
@columns_hash = nil
|
||||
@column_types = nil
|
||||
@column_defaults = nil
|
||||
@raw_column_defaults = nil
|
||||
@column_names = nil
|
||||
@content_columns = nil
|
||||
end
|
||||
|
|
|
@ -616,6 +616,34 @@ class DirtyTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
test "defaults with type that implements `type_cast_for_write`" do
|
||||
type = Class.new(ActiveRecord::Type::Value) do
|
||||
def type_cast(value)
|
||||
value.to_i
|
||||
end
|
||||
|
||||
def type_cast_for_write(value)
|
||||
value.to_s
|
||||
end
|
||||
|
||||
alias type_cast_for_database type_cast_for_write
|
||||
end
|
||||
|
||||
model_class = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = 'numeric_data'
|
||||
property :foo, type.new, default: 1
|
||||
end
|
||||
|
||||
model = model_class.new
|
||||
assert_not model.foo_changed?
|
||||
|
||||
model = model_class.new(foo: 1)
|
||||
assert_not model.foo_changed?
|
||||
|
||||
model = model_class.new(foo: '1')
|
||||
assert_not model.foo_changed?
|
||||
end
|
||||
|
||||
private
|
||||
def with_partial_writes(klass, on = true)
|
||||
old = klass.partial_writes?
|
||||
|
|
Loading…
Reference in a new issue