So, I have the following:
class Product < ActiveRecord::Base
# Has a bunch of common stuff about assembly hierarchy, etc
end
class SpecializedProduct < Product
# Has some special stuff that a "Product" can not do!
end
There's a manufacturing and assembly process in which data is captured about Products. At the time of capture the eventual product type is not known. after the Product record has been created in the database (perhaps days later) it may be necessary to turn that product into a specialized product and fill in the additional information. Not all products will become specialized, however.
I've been trying to use the following:
object_to_change = Product.find(params[:id])
object_to_change.becomes SpecializedProduct
object_to_change.save
Then, when I do a SpecializedProduct.all
the resulting set does not include object_to_change
. Instead object_to_change
is still listed in the database as Product
UPDATE "products" SET "type" = ?, "updated_at" = ? WHERE "products"."type" IN ('SpecializedProduct') AND "products"."id" = 30 [["type", "Product"], ["updated_at", Fri, 17 May 2013 10:28:06 UTC +00:00]]
So, after the call to .becomes SpecializedProduct
the .save
method is now using the right type, but it's not able to update the record because the WHERE
clause of the update is too specific.
Do I really need to access the type
attribute of the model directly? I'd really rather not.
Looking at the source of becomes
and becomes!
, it doesn't mutate the original object. You need to assign it to a new variable:
some_product = Product.find(params[:id])
specialized_product = some_product.becomes SpecializedProduct
specialized_product.save
Not sure how this will handle the primary key of the record, though, so you may need to do some additional finagling to make sure your relations don't get mangled.
You just need the bang version of the becomes method with (!) and save.
The difference between the two methods: becomes
creates a new instance of the new class with all the same attribute values of the original object. becomes!
also updates the type column.
object_to_change = Product.find(params[:id])
object_to_change.becomes! SpecializedProduct
object_to_change.save
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With