rails/rails — Issue #4933: Fallback behavior for class_attribute
Author: ohwillie
Created: 2012-02-07 23:53:19+00:00
State: open

Currently, ActiveSupport's ```class_attribute``` method allows for specification of class-level attributes that also propagate down to instances of a given class. However, when there is no value explicitly defined, methods defined by ```class_attribute``` return nil. In most circumstances this is okay, however, if you're implementing a pseudo-abstract class, it is probably better to raise a NotImplementedError than return nil if this method gets called on the abstract class.

Current behavior is as follows:

```ruby
class Foo
class_attribute :bar
end

class Baz
end

class Qux
self.bar = 'quux'
end

puts Foo.bar.inspect #=> nil
puts Baz.bar.inspect #=> nil
puts Qux.bar.inspect #=> "quux"
puts Foo.new.bar.inspect #=> nil
puts Baz.new.bar.inspect #=> nil
puts Qux.new.bar.inspect #=> "quux"
```

I propose that the following behavior be supported:

```ruby
class Foo
class_attribute :bar, :default => lambda { |attribute| raise NotImplementedError.new("#{attribute} is undefined") }
end

class Baz
end

class Qux
self.bar = 'quux'
end

puts Foo.bar.inspect # raises error
puts Baz.bar.inspect # raises error
puts Qux.bar.inspect #=> "quux"
puts Foo.new.bar.inspect #=> raises error
puts Baz.new.bar.inspect #=> raises error
puts Qux.new.bar.inspect #=> "quux"
```

By allowing ```class_attribute``` to take a default lambda (and perhaps a raw value), classes can cleanly implement abstract values in a generic fashion.