1
0
Fork 0
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:
Sean Griffin 2014-06-03 08:23:30 -06:00
parent 098bb63ae4
commit ed559d4b00
5 changed files with 40 additions and 2 deletions

View file

@ -52,7 +52,7 @@ module ActiveRecord
end
def extract_default(default)
type_cast_for_write(type_cast(default))
type_cast(default)
end
end
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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?