diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index b8acc5f148ba39cb1dbe27ea51c221fb78d42345..b4d8b7b372080790e1549edf36c152a649c63c65 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,5 +1,9 @@ *SVN* +* Added ActiveRecord::Base#becomes to turn a record into one of another class (mostly relevant for STIs) [DHH]. Example: + + render :partial => @client.becomes(Company) # renders companies/company instead of clients/client + * Fixed that to_xml should not automatically pass :procs to associations included with :include #10162 [chuyeow] * Fix documentation typo introduced in [8250]. Closes #10339 [Henrik N] diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 65dc7275dffc52b1395875d69a3641c6805f0dd0..c7db48167caee29b2f33aee102e149bbef5090e0 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1806,6 +1806,20 @@ def clone record end + # Returns an instance of the specified klass with the attributes of the current record. This is mostly useful in relation to + # single-table inheritance structures where you want a subclass to appear as the superclass. This can be used along with record + # identification in Action Pack to allow, say, Client < Company to do something like render :partial => @client.becomes(Company) + # to render that instance using the companies/company partial instead of clients/client. + # + # Note: The new instance will share a link to the same attributes as the original class. So any change to the attributes in either + # instance will affect the other. + def becomes(klass) + returning klass.new do |became| + became.instance_variable_set("@attributes", @attributes) + became.instance_variable_set("@new_record", new_record?) + end + end + # Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. # Note: This method is overwritten by the Validation module that'll make sure that updates made with this method # aren't subjected to validation checks. Hence, attributes can be updated even if the full object isn't valid. diff --git a/activerecord/test/base_test.rb b/activerecord/test/base_test.rb index 3c1cac0d49b1347e28701920e47c1c4b874ce2fe..e8954b69d0ba51cc8ecc5fa7b3cf1fc857812e04 100755 --- a/activerecord/test/base_test.rb +++ b/activerecord/test/base_test.rb @@ -1737,4 +1737,9 @@ def test_attribute_for_inspect assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on) assert_equal '"This is some really long content, longer than 50 ch..."', t.attribute_for_inspect(:content) end -end + + def test_becomes + assert_kind_of Reply, topics(:first).becomes(Reply) + assert_equal "The First Topic", topics(:first).becomes(Reply).title + end +end \ No newline at end of file