move ActiveRecord::Persistance#becomes logic into initialize block

This commit is contained in:
Sampson Crowley 2020-09-20 10:24:19 -06:00
parent 7cdc174471
commit bdaeee19f9
3 changed files with 27 additions and 6 deletions

View File

@ -569,12 +569,15 @@ module ActiveRecord
# If you want to change the sti column as well, use #becomes! instead.
def becomes(klass)
became = klass.allocate
became.send(:initialize)
became.instance_variable_set(:@attributes, @attributes)
became.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
became.instance_variable_set(:@new_record, new_record?)
became.instance_variable_set(:@destroyed, destroyed?)
became.errors.copy!(errors)
became.send(:initialize) do |becoming|
becoming.instance_variable_set(:@attributes, @attributes)
becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
becoming.instance_variable_set(:@new_record, new_record?)
becoming.instance_variable_set(:@destroyed, destroyed?)
becoming.errors.copy!(errors)
end
became
end

View File

@ -227,6 +227,16 @@ class InheritanceTest < ActiveRecord::TestCase
assert_kind_of Cabbage, cabbage
end
def test_becomes_sets_variables_before_initialization_callbacks
vegetable = Vegetable.create!(name: "yelling carrot")
assert_kind_of Vegetable, vegetable
assert_equal "yelling carrot", vegetable.name
yelling_veggie = vegetable.becomes(YellingVegetable)
assert_equal "YELLING CARROT", yelling_veggie.name, "YellingVegetable name should be YELLING CARROT"
assert_equal "YELLING CARROT", vegetable.name, "Vegetable name should be YELLING CARROT after becoming a YellingVegetable"
end
def test_becomes_and_change_tracking_for_inheritance_columns
cucumber = Vegetable.find(1)
cabbage = cucumber.becomes!(Cabbage)

View File

@ -23,3 +23,11 @@ end
class RedCabbage < Cabbage
belongs_to :seller, class_name: "Company"
end
class YellingVegetable < Vegetable
after_initialize :format_name
def format_name
self.name = name&.upcase
end
end