Let's say you have a persisted instance of a model, RedCar
, that uses STI and
is descended from Car
. You have an action that changes the type of the record
to BlueCar
. You use #becomes
to cast the record to the new type before
the save because you want to use the validations and callbacks from the new
model:
But wait! If you retrieve car
from the database again you'll see that it's
still an instance of RedCar
. In fact, you'll see that no changes are saved to
the database:
Doing an explicit update_column
on type
here doesn't help:
Also, note: no exceptions are raised. We'll save you any more head-scratching by pointing out the SQL that is generated:
The problem is that Rails STI scopes the statement to WHERE `cars`.`type` IN
('BlueCar')
even for UPDATES and even when you're trying to change the type
itself. Woops.
So what's the solution? As far as we can tell you have to do a separate update after you've passed validation. We ended up implementing this in a before_filter along these lines: