Tue, 29 Jul 2008

Inheritable Attributes in Rails

During a debugging session the other day, I found myself digging into how Rails implements inheritable attributes. These are an extension to the Class class and deeply intertwined in the inner workings of Rails. They’re part of ActiveSupport. I haven’t seen much on the net discussing them, and I don’t know whether that’s because few people have to deal with them directly, they’re mundane, or my search skills are failing. In any case, I decided to jot down my discoveries.

Inheritable attributes are kind of like class variables, except they’re copy-on-subclass. The subclass gets a copy of these from the superclass, but the subclass can further modify them independently. One major use of them in Rails is for STI (Single Table Inheritance) subclasses to inherit the superclass’ associations. The actual association declarations in the superclass (such as has_many, belongs_to, etc.) create an object stored in an inheritable attribute called reflections. Then once a subclass is created it gets a copy of this array of reflections and can further refine or extend them. Cool stuff.

But there’s a dark side. I mentioned above that this was found in a debugging session, not just a random exploration through the Rails source. The way these work depends on the Class#inherited method, which is called on a superclass whenever a subclass is defined and the subclass is passed as a parameter. This is where the actual copy-on-subclass logic occurs. If another monkey-patcher messes with the inherited method, weird things can happen, like a STI subclass losing access to the superclass’ associations.

However, once they’re understood, it’s not so mysterious. Not only that, but they’re a useful item to keep in your bag of tricks. There are analogs to attr_accessor and similar methods called class_inheritable_accessor as well as special methods for array and hash versions for those occasions when you want a subclass to have copy-on-subclass class variables.

writebacks

writebacks...

trackback

TrackBack ping me at:

http://gigavolt.net/blog.trackback

comment...

 
Name:
URL/Email: [http://... or mailto:you@wherever] (optional)
Title: (optional)
Comments:
Save my Name and URL/Email for next time