« My RubyConf India 2010 Talk Highlights | Main | Excellence Is In the Details: GMail EOM »

April 11, 2010

The Rails 3 Way Highlights: ActiveSupport's Class.class_attribute

As I'm wrapping up work on The Rails 3 Way, I'm coming across little nuggets of interesting content suitable for blogging. Time permitting, I'll publish them here over the course of the next few months.


In this case, I cover a new ActiveSupport core extension to Ruby's Class object. It allows creation of class-level attributes in a simple and powerful manner that I think is a lot clearer than the mess of cattr_ and class_inheritable_ methods that precede it.

class_attribute(*attrs)

The class_attribute method declaratively defines one or more class-level attributes whose value is inheritable and overwritable by subclasses and instances, like so:

class Base
  class_attribute :setting
end


class Subclass < Base
end


>> Base.setting = "foo"
=> "foo"


>> Subclass.setting
=> "foo"


>> Subclass.setting = "bar"
=> "bar"


>> Subclass.setting
=> "bar"


>> Base.setting
=> "foo"


This behavior matches normal Ruby method inheritance: think of writing an attribute on a subclass as overriding the parent's reader method. Instances may overwrite the class value in the same way. (Note that the following code samples create anonymous classes to illustrate usage in a more concise fashion.)

klass = Class.new { class_attribute :setting }
object = klass.new


>> klass.setting = "foo
=> "foo"


>> object.setting = "bar"
=> "bar"


>> klass.setting
=> "foo"


To opt out of the instance writer method, pass :instance_writer => false.

klass = Class.new { class_attribute :setting, :instance_writer => false }


>> klass.new.setting
=> NoMethodError


The class_attribute method also works with singleton classes, as can be seen in the following example.

klass = Class.new { class_attribute :setting }


>> klass.singleton_class.setting = "foo"
=> "foo"


For convenience, a query method is defined as well, which allows you to see if an attribute has been set on a particular class instance. 

klass = Class.new { class_attribute :setting }


>> klass.setting?
=> false


>> klass.setting = "foo"
=> "foo"


>> klass.setting?
=> true


If you read this far you should probably follow me on twitter:

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00e54fdca911883301347fcd2d5d970c

Listed below are links to weblogs that reference The Rails 3 Way Highlights: ActiveSupport's Class.class_attribute:

Sponsored By

Flattr

or visit my my homepage

My Companies

My Latest Books

My Book Series