Basic tech stuff

Programming and Linux administration

Rails: belongs_to :polymorphic and inheritance

Posted by Daniel Brahneborg on 2007 May 10

The flag :polymorphic option for belongs_to associations is extremely useful, especially when implementing an authorization system. Let’s say that I have a Permission class that points to either a House or a Car:

class Permission < ActiveRecord::Base; belongs_to :authobject, :polymorphic => true; end
class House < ActiveRecord::Base; has_many :permissions, :as => 'authobject'; end
class Car < ActiveRecord::Base; has_many :permissions, :as => 'authobject'; end

This works just fine, making it possible both to find the object that a Permission is for, and the relevant Permissions for a certain object. In the column authobject_type you get the strings “House” and “Car”, respectively.

Now the problem: We want to replace the Car class with an abstract Vehicle class, with subclasses Car and Boat:

class Vehicle < ActiveRecord::Base; has_many :permissions, :as => 'authobject'; end
class Car < Vehicle; end
class Boat < Vehicle; end

In Rails version 1.2.3 this puts the string “Vehicle” in the Permissions.authobject_type column, which causes lots of stuff to fail. In my case, a bunch of test cases that simply created a Permission and made sure it could be found again. Suddenly it couldn’t.

The problem was this bug: http://dev.rubyonrails.org/ticket/6485, with a patch that makes sure that the real class name in the authobject_type field. The Rails documentation says you should store the base class in the authobject_type field, but that simply isn’t right, since it makes it impossible to load the right subclass. Since we still want to store permissions to Houses, it’s important that we store the exact class name.

Edit 2007-05-16: The problem is still not completely solved, since :dependent => :destroy still uses the base class name instead of the correct one. Since following the relationship works, you have to loop and destroy the objects manually.

Andra bloggar om: , , .

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: