Rails Development: Naming Conflicts on a Polymorphic has_many

A little while ago I stumbled upon an interesting issue in a Rails application. If the name of the polymorphic relationship for a belongs_to has the same name as one of the belonging classes and two instances of two different belong_to classes have the same ID, they will report each others' instances.

This alien only has one ship

For example:
Imagine a Ship belongs to a Person polymorphically. If a Person and an Alien both have many ships, they can report both person and alien ships where the person and alien have the same id.

The solution is to make sure that Rails knows that it is a polymorphic relationship from the has_many side by using the :as option.

So imagine a Backpack also belongs to a Person polymorphically. If Person and Alien specify that they have many backpacks :as => :person then everything works as expected.

For this example repository, run rake to see the failing and passing tests demonstrating the issue.

It is important to remember that while Rails is really great with its defaults and assumptions about how you do things, if you let your naming overlap (which you should be avoiding, but let’s say you’ve got this issue anyway) you will probably need to be more specific with your model relationships than you are used to.

This problem is particularly interesting because it is easy for it to go unnoticed, since it only occurs when the IDs of the colliding models match, which depending on other filtering conditions in your app, might not be very often.

It is probably not very often that the name of polymorphic column matches one of your models. In general, this should probably be avoided, but specifying the :as => :column_name is a good idea as well.

Have you come across this issue in rails development? Comment and let us know.

Image source


comments powered by Disqus