loading...

How do I approach renaming a well-used model in Rails.

maxshelley profile image Max Shelley ใƒปUpdated on ใƒป2 min read

Hi ๐Ÿ‘‹ I'm looking for some help and would really appreciate any feedback. I'm working on an established Rails app, we have a new use-case in the business and I'm considering how to approach it in code. We currently have a Charity model in the app, it's widely used and has a lot of associations, but we've tried not to overload it (we use services classes to try and prevent the model having to do too much other than represent the charity).

We will now have organisations coming into the app that are not registered charities, but which will have much of the same functionality (they're social enterprises, community interest companies etc). Long term, as they're so similar I want them all to be instances of Organisation (we may well start working with other types of orgs in the future).

What's the best way to go about that transition from Charity to Organisation? I don't really like the idea of a single โ€˜rename everythingโ€™ project as the risk is pretty high. Although maybe that is viable if there are great tools out there? I'm worried about missing something and the mass-renaming in tests meaning that it's not caught

My first thought is to create Organisation as a parent class of Charity, but add nothing to it and set it's table_name to 'charities' (or perhaps vice versa, not sure which way around would be best to do that).

Then begin the long job of transitioning all uses of Charity to Organisation, once that's done, then creating a database table called organisations (while still having the Organisation class point at the charities table). We then add callbacks to Charity to keep the two tables in sync (so as a charity is updated or added, it updates the organisations table too). Once all that's done, we can then point the Organisation class at the 'organisations' table and we're done, so we can remove the Charity class and charities table altogether.

I hope that makes some sense. If anyone has been through a project like that, I'd love to hear what worked, what didn't work for you. Thanks!

Discussion

pic
Editor guide
Collapse
adamwhittingham profile image
Adam Whittingham

Hey Max,

I totally agree with your initial idea:
You could rename the Charity model to Organisation with the table_name set to the charity table, and then create a new empty Charity model which inherits from Organisation.
This will let you use the two classes interchangably while you refactor methods/scopes/etc to only refer to Organisaton.
Eventually, when you think you've renamed all the references, you can simply delete the empty Charity class and run your tests.

Syncing the two tables sounds like there's too much risk of a desync as you move functionality from one class to the other.

The one downside to all this is that your deployment to finally rename the table would require a breif outage and restart. If (and only if) this can't be done during a quiet time and you need full uptime, would I consider trying to sync the tables, as it required an order of magnitude more effort. If you can stomach a sub-30 second outage to rename & restart, I'd personally do that.

PS- a tangent but maybe a useful one: we handle similiar issues at the column level by using the strong_migrations gem to prevent any operations that would lock a table/column or require an outage to ensure out migrations are safey to run with as little downtime as possible, but it does result in an increase in dev time for things like column renames.