aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/base.rb49
-rw-r--r--activerecord/test/cases/duplication_test.rb19
2 files changed, 38 insertions, 30 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 0d3df938e6..be8ebd4d59 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1382,30 +1382,6 @@ MSG
result
end
- # Cloned objects have no id assigned and are treated as new records. Note that this is a "shallow" clone
- # as it copies the object's attributes only, not its associations. The extent of a "deep" clone is
- # application specific and is therefore left to the application to implement according to its need.
- def initialize_copy(other)
- _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
- cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
- cloned_attributes.delete(self.class.primary_key)
-
- @attributes = cloned_attributes
-
- @changed_attributes = {}
- attributes_from_column_definition.each do |attr, orig_value|
- @changed_attributes[attr] = orig_value if field_changed?(attr, orig_value, @attributes[attr])
- end
-
- clear_aggregation_cache
- clear_association_cache
- @attributes_cache = {}
- @persisted = false
- ensure_proper_type
-
- populate_with_current_scope_attributes
- end
-
# Initialize an empty model object from +coder+. +coder+ must contain
# the attributes necessary for initializing an empty model object. For
# example:
@@ -1420,7 +1396,7 @@ MSG
@attributes = coder['attributes']
@attributes_cache, @previously_changed, @changed_attributes = {}, {}, {}
@readonly = @destroyed = @marked_for_destruction = false
- @persisted = false
+ @persisted = true
_run_find_callbacks
_run_initialize_callbacks
end
@@ -1615,15 +1591,32 @@ MSG
@attributes.frozen?
end
+ # Duped objects have no id assigned and are treated as new records. Note
+ # that this is a "shallow" clone as it copies the object's attributes
+ # only, not its associations. The extent of a "deep" dup is application
+ # specific and is therefore left to the application to implement according
+ # to its need.
def initialize_dup(other)
super
- init_with 'attributes' => other.attributes
+ cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast)
+ cloned_attributes.delete(self.class.primary_key)
+
+ @attributes = cloned_attributes
+ @changed_attributes = other.changed_attributes.dup
+ @attributes_cache = {}
+ @persisted = false
+
+ _run_after_initialize_callbacks if respond_to?(:_run_after_initialize_callbacks)
+ clear_aggregation_cache
+ clear_association_cache
+ ensure_proper_type
+ populate_with_current_scope_attributes
self
end
- # Returns duplicated record with unfreezed attributes.
- def dup
+ def initialize_clone(other)
super
+ @persisted = other.persisted?
end
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
diff --git a/activerecord/test/cases/duplication_test.rb b/activerecord/test/cases/duplication_test.rb
index 610894a03e..f9d614230b 100644
--- a/activerecord/test/cases/duplication_test.rb
+++ b/activerecord/test/cases/duplication_test.rb
@@ -6,7 +6,7 @@ module ActiveRecord
fixtures :topics
def test_dup
- assert !Minimalistic.new.freeze.dup.frozen?
+ assert !Topic.new.freeze.dup.frozen?
end
def test_dup_not_persisted
@@ -26,6 +26,7 @@ module ActiveRecord
def test_clone_persisted
topic = Topic.first
cloned = topic.clone
+ assert topic.persisted?, 'topic persisted'
assert cloned.persisted?, 'topic persisted'
assert !cloned.new_record?, 'topic is not new'
end
@@ -37,7 +38,21 @@ module ActiveRecord
cloned = topic.clone
assert cloned.persisted?, 'topic persisted'
assert !cloned.new_record?, 'topic is not new'
- assert cloned.frozen?, 'topic is frozen'
+ assert cloned.frozen?, 'topic should be frozen'
+ end
+
+ def test_dup_with_modified_attributes
+ topic = Topic.first
+ topic.author_name = 'Aaron'
+ duped = topic.dup
+ assert_equal 'Aaron', duped.author_name
+ end
+
+ def test_dup_with_changes
+ topic = Topic.first
+ topic.author_name = 'Aaron'
+ duped = topic.dup
+ assert_equal topic.changes, duped.changes
end
end
end