diff options
author | Yves Senn <yves.senn@gmail.com> | 2014-05-29 21:53:58 +0200 |
---|---|---|
committer | Yves Senn <yves.senn@gmail.com> | 2014-05-29 21:53:58 +0200 |
commit | f14164c573b81fcff382950d924481ea7b4a9b10 (patch) | |
tree | 9672c1288642f592562555c883cd901d6f5c93e9 /activerecord/lib | |
parent | 4584be9b8bd15277cc05e8729830247df45d46dc (diff) | |
parent | 2eb547a4d9cfb4ed1c92397921402048162f5fc8 (diff) | |
download | rails-f14164c573b81fcff382950d924481ea7b4a9b10.tar.gz rails-f14164c573b81fcff382950d924481ea7b4a9b10.tar.bz2 rails-f14164c573b81fcff382950d924481ea7b4a9b10.zip |
Merge pull request #15398 from sgrif/sg-serialized-types
Refactor serialized types to be partially defined as custom properties
Diffstat (limited to 'activerecord/lib')
8 files changed, 50 insertions, 38 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 47c6f94ba7..e8c27cb8b8 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -58,32 +58,18 @@ module ActiveRecord Coders::YAMLColumn.new(class_name_or_coder) end + type = columns_hash[attr_name.to_s].cast_type + if type.serialized? + type = type.subtype + end + property attr_name, ActiveRecord::Type::Serialized.new(type) + # merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy # has its own hash of own serialized attributes self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder) end end - class Type # :nodoc: - delegate :type, :type_cast_for_database, to: :@column - - def initialize(column) - @column = column - end - - def type_cast(value) - if value.state == :serialized - value.unserialized_value @column.type_cast value.value - else - value.unserialized_value - end - end - - def accessor - ActiveRecord::Store::IndifferentHashAccessor - end - end - class Attribute < Struct.new(:coder, :value, :state) # :nodoc: def unserialized_value(v = value) state == :serialized ? unserialize(v) : value diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index a62617ab47..42650e332d 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -15,8 +15,10 @@ module ActiveRecord attr_reader :name, :default, :cast_type, :null, :sql_type, :default_function - delegate :type, :precision, :scale, :limit, :klass, :text?, :number?, :binary?, - :type_cast, :type_cast_for_write, :type_cast_for_database, to: :cast_type + delegate :type, :precision, :scale, :limit, :klass, :accessor, + :text?, :number?, :binary?, :serialized?, + :type_cast, :type_cast_for_write, :type_cast_for_database, + to: :cast_type # Instantiates a new column in the table. # diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb index 9a5e2d05ef..a579746815 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb @@ -35,10 +35,6 @@ module ActiveRecord end end # :startdoc: - - def accessor - cast_type.accessor - end end end end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index a4e10ed2e7..ad6428d8a8 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -224,14 +224,6 @@ module ActiveRecord def decorate_columns(columns_hash) # :nodoc: return if columns_hash.empty? - @serialized_column_names ||= self.columns_hash.keys.find_all do |name| - serialized_attributes.key?(name) - end - - @serialized_column_names.each do |name| - columns_hash[name] = AttributeMethods::Serialization::Type.new(columns_hash[name]) - end - @time_zone_column_names ||= self.columns_hash.find_all do |name, col| create_time_zone_conversion_attribute?(name, col) end.map!(&:first) @@ -299,7 +291,6 @@ module ActiveRecord @dynamic_methods_hash = nil @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column @relation = nil - @serialized_column_names = nil @time_zone_column_names = nil @cached_time_zone = nil end diff --git a/activerecord/lib/active_record/properties.rb b/activerecord/lib/active_record/properties.rb index cc1e8b45c1..7fe59ccce4 100644 --- a/activerecord/lib/active_record/properties.rb +++ b/activerecord/lib/active_record/properties.rb @@ -64,6 +64,7 @@ module ActiveRecord # store_listing.price_in_cents # => 1000 def property(name, cast_type) name = name.to_s + clear_properties_cache # Assign a new hash to ensure that subclasses do not share a hash self.user_provided_columns = user_provided_columns.merge(name => connection.new_column(name, nil, cast_type)) end @@ -80,9 +81,7 @@ module ActiveRecord def reset_column_information # :nodoc: super - - @columns = nil - @columns_hash = nil + clear_properties_cache end private @@ -97,6 +96,11 @@ module ActiveRecord existing_columns + new_columns end + + def clear_properties_cache + @columns = nil + @columns_hash = nil + end end end end diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index 2c26477201..e9b827886a 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -10,6 +10,7 @@ require 'active_record/type/decimal' require 'active_record/type/decimal_without_scale' require 'active_record/type/float' require 'active_record/type/integer' +require 'active_record/type/serialized' require 'active_record/type/string' require 'active_record/type/text' require 'active_record/type/time' diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb new file mode 100644 index 0000000000..cc7513ca2a --- /dev/null +++ b/activerecord/lib/active_record/type/serialized.rb @@ -0,0 +1,28 @@ +module ActiveRecord + module Type + class Serialized < SimpleDelegator # :nodoc: + attr_reader :subtype + + def initialize(subtype) + @subtype = subtype + super + end + + def type_cast(value) + if value.respond_to?(:unserialized_value) + value.unserialized_value(super(value.value)) + else + super + end + end + + def serialized? + true + end + + def accessor + ActiveRecord::Store::IndifferentHashAccessor + end + end + end +end diff --git a/activerecord/lib/active_record/type/value.rb b/activerecord/lib/active_record/type/value.rb index 72d27197d5..a5493be8f2 100644 --- a/activerecord/lib/active_record/type/value.rb +++ b/activerecord/lib/active_record/type/value.rb @@ -43,6 +43,10 @@ module ActiveRecord false end + def serialized? + false + end + def klass ::Object end |