diff options
author | Sean Griffin <sean@thoughtbot.com> | 2014-06-07 13:46:22 -0600 |
---|---|---|
committer | Sean Griffin <sean@thoughtbot.com> | 2014-06-13 10:20:54 -0600 |
commit | 6f08db05c00ea05c38d7d9d7bea757a903786a83 (patch) | |
tree | bdf051f4286c280d7c724ae05f18692078e1524e /activerecord/lib/active_record/core.rb | |
parent | 70b931f846cb212f3db16f35a10094fb727a57e2 (diff) | |
download | rails-6f08db05c00ea05c38d7d9d7bea757a903786a83.tar.gz rails-6f08db05c00ea05c38d7d9d7bea757a903786a83.tar.bz2 rails-6f08db05c00ea05c38d7d9d7bea757a903786a83.zip |
Introduce an Attribute object to handle the type casting dance
There's a lot more that can be moved to these, but this felt like a good
place to introduce the object. Plans are:
- Remove all knowledge of type casting from the columns, beyond a
reference to the cast_type
- Move type_cast_for_database to these objects
- Potentially make them mutable, introduce a state machine, and have
dirty checking handled here as well
- Move `attribute`, `decorate_attribute`, and anything else that
modifies types to mess with this object, not the columns hash
- Introduce a collection object to manage these, reduce allocations, and
not require serializing the types
Diffstat (limited to 'activerecord/lib/active_record/core.rb')
-rw-r--r-- | activerecord/lib/active_record/core.rb | 37 |
1 files changed, 18 insertions, 19 deletions
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 7edaf256c7..834f6a7eb9 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -249,10 +249,13 @@ module ActiveRecord # # Instantiates a single new object # User.new(first_name: 'Jamie') def initialize(attributes = nil, options = {}) - defaults = self.class.raw_column_defaults.dup - defaults.each { |k, v| defaults[k] = v.dup if v.duplicable? } + defaults = {} + self.class.raw_column_defaults.each do |k, v| + default = v.duplicable? ? v.dup : v + defaults[k] = Attribute.from_database(default, type_for_attribute(k)) + end - @raw_attributes = defaults + @attributes = defaults @column_types_override = nil @column_types = self.class.column_types @@ -278,13 +281,12 @@ module ActiveRecord # post.init_with('attributes' => { 'title' => 'hello world' }) # post.title # => 'hello world' def init_with(coder) - @raw_attributes = coder['raw_attributes'] + @attributes = coder['attributes'] @column_types_override = coder['column_types'] @column_types = self.class.column_types init_internals - @attributes = coder['attributes'] if coder['attributes'] @new_record = coder['new_record'] self.class.define_attribute_methods @@ -323,12 +325,9 @@ module ActiveRecord ## def initialize_dup(other) # :nodoc: - cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) - - @raw_attributes = cloned_attributes - @raw_attributes[self.class.primary_key] = nil - @attributes = other.clone_attributes(:read_attribute) - @attributes[self.class.primary_key] = nil + pk = self.class.primary_key + @attributes = other.clone_attributes + @attributes[pk] = Attribute.from_database(nil, type_for_attribute(pk)) run_callbacks(:initialize) unless _initialize_callbacks.empty? @@ -354,7 +353,8 @@ module ActiveRecord # Post.new.encode_with(coder) # coder # => {"attributes" => {"id" => nil, ... }} def encode_with(coder) - coder['raw_attributes'] = @raw_attributes + # FIXME: Remove this when we better serialize attributes + coder['raw_attributes'] = attributes_before_type_cast coder['attributes'] = @attributes coder['column_types'] = @column_types_override coder['new_record'] = new_record? @@ -387,13 +387,13 @@ module ActiveRecord # accessible, even on destroyed records, but cloned models will not be # frozen. def freeze - @raw_attributes = @raw_attributes.clone.freeze + @attributes = @attributes.clone.freeze self end # Returns +true+ if the attributes hash has been frozen. def frozen? - @raw_attributes.frozen? + @attributes.frozen? end # Allows sort on objects @@ -422,9 +422,9 @@ module ActiveRecord # Returns the contents of the record as a nicely formatted string. def inspect - # We check defined?(@raw_attributes) not to issue warnings if the object is + # We check defined?(@attributes) not to issue warnings if the object is # allocated but not initialized. - inspection = if defined?(@raw_attributes) && @raw_attributes + inspection = if defined?(@attributes) && @attributes self.class.column_names.collect { |name| if has_attribute?(name) "#{name}: #{attribute_for_inspect(name)}" @@ -523,11 +523,10 @@ module ActiveRecord def init_internals pk = self.class.primary_key - @raw_attributes[pk] = nil unless @raw_attributes.key?(pk) + @attributes[pk] ||= Attribute.from_database(nil, type_for_attribute(pk)) @aggregation_cache = {} @association_cache = {} - @attributes = {} @readonly = false @destroyed = false @marked_for_destruction = false @@ -550,7 +549,7 @@ module ActiveRecord def thaw if frozen? - @raw_attributes = @raw_attributes.dup + @attributes = @attributes.dup end end end |