Search code examples
ruby-on-railsrails-activerecordsingle-table-inheritance

Rename single table inheritance rails model class name without changing existing data


I have a ActiveRecord STI subclass that I want to rename (case sensitive change).

But if I change the class name of the subclass ActiveRecord cannot instantiate the existing records anymore because the old class name resides in the type column of the base table.

How can I change the name of the class without changing content in the database so that renaming has the smallest amount of impact.

Example:

The class Uld < Component should become ULD < Component. The renaming approach would require a db migration

def up
  Component.where(type: 'Uld').update_all(type: 'ULD')
end

def down
  Component.where(type: 'ULD').update_all(type: 'Uld')
end

But with a deployment on heroku this would cause issues because the data change comes first and the code does not even have the new class name available. Therefore this section of the codebase would not be usable for a couple of minutes. Not nice for a change that users don't even care about :/


Solution

  • This is how you could do it:

    1. Create ULD < Component component/file that is a copy of Uld < Component. I.e. have 2 components, don't remove Uld
    2. In places where you previously fetched Uld make it so that now you fetch records where type is Uld or ULD
    3. In places where you created new Uld records make it so that it instead creates new ULD records
    4. Deploy these changes without any migrations, this way your servers will be backwards compatible with Uld but would also work with ULD
    5. Deploy your migration now
    6. Finally, remove all the mentions/files related to the old Uld and deploy again