Ruby is the language for coding brevity with elegance. The more you “get” Ruby, the less code you end up writing. One of the ways you do this is to just metacode the things you find yourself doing a lot and become more productive. And that’s a beautiful thing!
Recently, I’ve found myself writing and rewriting class attribute accessors, like
class Foo
def self.bar
@@bar
end
def self.bar=(bar)
@@bar = bar
end
end
Being from the old school, while I’m not adverse to just using the @@
directly inside the class, I prefer some encapsulation.
And when you want to expose the class’ innards, you need to write these methods anyway.
This if fine, but it gets a bit too verbose for me.
Instance attributes are exposed easily with the attr
methods
class Mumble
attr_accessor :barfle
end
which creates the barfle
and barfle=
instance methods.
What I want is an analogous
class Foo
class_attr_accessor :bar
end
to create my self.bar
and self.bar=
methods.
Metaprogramming to the rescue!
class Module
def class_attr_reader(*kattrs)
kattrs.each { |kattr|
ka = kattr.to_s
reader = <<EOS
def #{ka}
@@ka
end
EOS
self.module_eval reader
}
end
def class_attr_writer(*kattrs)
kattrs.each { |kattr|
ka = kattr.to_s
writer = <<EOS
def self.#{ka}=(#{ka})
@@#{ka} = #{ka}
end
EOS
self.module_eval writer
}
end
def class_attr_accessor(*kattrs)
class_attr_reader(*kattrs)
class_attr_writer(*kattrs)
end
end
Sweetness. I just love Ruby!