Increasingly Functional.
by Joshua Miller | on Twitter | on the web | on github

Why class_inheritable_accessor

September 17th 2010

Tagged: ruby

While working on loose_change tonight, I ran into a situation I hadn't run into before in Ruby — the need to keep track of attributes on a class that can be inherited. The solution is class_inheritable_accessor. I'd come across blog articles on the subject before, but for the most part, my eyes glazed over. There's a limit to how much jargon I can process without a concrete example to compare. Here's a walkthrough of the problem and the solution.

Let's say you need to keep an attribute on a class (not an instance)

require 'active_support'
require 'active_support/core_ext' # (I'll assume these throughout)

class Payment
  class_attribute :acceptable_payors
end

Payment.acceptable_payors = [:tom, :dick]

Great! Now we know who we'll take money from.

Now, let's add a credit card payment class:

class Cash < Payment
end

We want to allow the slightly less trustworthy Harry to pay us, as long as it's cash:

Cash.acceptable_payors << :harry

But now, let's check our general acceptable payors again:

Payment.acceptable_payors #=> [:tom, :dick, :harry]

Since class_attribute just passes a pointer to the attribute around, subclasses who change something change it for everyone.

So, class_inheritable_accessor to the rescue. Swap it in for class_attribute, and your end result will be:

Cash.acceptable_payors #=> [:tom, :dick, :harry]
Payment.acceptable_payors #=> [:tom, :dick]