AR::Base#clone fixed to set dirty bits for cloned object

[#2919 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
This commit is contained in:
pleax
2010-05-17 01:47:56 +04:00
committed by Jeremy Kemper
parent e1a340a91d
commit 4db10bce7b
2 changed files with 57 additions and 1 deletions

View File

@@ -1463,12 +1463,18 @@ module ActiveRecord #:nodoc:
callback(:after_initialize) if respond_to_without_attributes?(:after_initialize)
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
@attributes_cache = {}
@new_record = true
ensure_proper_type
@changed_attributes = other.changed_attributes.dup
if scope = self.class.send(:current_scoped_methods)
create_with = scope.scope_for_create

View File

@@ -1456,6 +1456,56 @@ class BasicsTest < ActiveRecord::TestCase
assert_kind_of Client, clone
end
def test_clone_of_new_object_with_defaults
developer = Developer.new
assert !developer.name_changed?
assert !developer.salary_changed?
cloned_developer = developer.clone
assert !cloned_developer.name_changed?
assert !cloned_developer.salary_changed?
end
def test_clone_of_new_object_marks_attributes_as_dirty
developer = Developer.new :name => 'Bjorn', :salary => 100000
assert developer.name_changed?
assert developer.salary_changed?
cloned_developer = developer.clone
assert cloned_developer.name_changed?
assert cloned_developer.salary_changed?
end
def test_clone_of_new_object_marks_as_dirty_only_changed_attributes
developer = Developer.new :name => 'Bjorn'
assert developer.name_changed? # obviously
assert !developer.salary_changed? # attribute has non-nil default value, so treated as not changed
cloned_developer = developer.clone
assert cloned_developer.name_changed?
assert !cloned_developer.salary_changed? # ... and cloned instance should behave same
end
def test_clone_of_saved_object_marks_attributes_as_dirty
developer = Developer.create! :name => 'Bjorn', :salary => 100000
assert !developer.name_changed?
assert !developer.salary_changed?
cloned_developer = developer.clone
assert cloned_developer.name_changed? # both attributes differ from defaults
assert cloned_developer.salary_changed?
end
def test_clone_of_saved_object_marks_as_dirty_only_changed_attributes
developer = Developer.create! :name => 'Bjorn'
assert !developer.name_changed? # both attributes of saved object should be threated as not changed
assert !developer.salary_changed?
cloned_developer = developer.clone
assert cloned_developer.name_changed? # ... but on cloned object should be
assert !cloned_developer.salary_changed? # ... BUT salary has non-nil default which should be threated as not changed on cloned instance
end
def test_bignum
company = Company.find(1)
company.rating = 2147483647