From: Joel VanderWerf Date: 2010-06-22T09:42:14+09:00 Subject: Re: Got to be a better way to code class variables.... Dave Howell wrote: > I'm trying to set up an object with overridable defaults, so it will act like this: > > >> s1 = Smee.new > => # > >> s1.middle = 'hi' > => "hi" > >> s1 > => # > >> Smee.front = "O" > => "O" > >> s2 = Smee.new > => # > >> s1 => # > >> Smee.middle = "utu" > => "utu" > >> s1.middle > => "hi" > >> s2.middle > => "utu" > > So I can set the properties of an instance of Smee, but if I don't set them, or if I set them back to nil, then the corresponding values that I set on the class will take their place. > > This is the closest thing I've gotten so far and it seems ludicrously clunky. > > class Smee > attr_writer :front, :middle, :back > > class << self > attr_accessor :front, :middle, :back > end > > def front > @front || Smee.front > end > > def middle > @middle || Smee.middle > end > > def back > @back || Smee.back > end > end > > I'd like to have other methods that worked the same on the class and the instance, but the only way I can figure out how is to type every single method twice. There has *got* to be some terribly clever ruby-esque way of including instance methods as class methods or vice versa, no? > > Some metaprogging... module Overridable def overridable(*names) names.each do |name| attr_writer name (class << self; self; end).class_eval do attr_accessor name end class_eval %{ def #{name} @#{name} || self.class.#{name} end } end end end class Smee extend Overridable overridable :front self.front = 12 end sm0 = Smee.new sm1 = Smee.new sm1.front = 56 p sm0.front, sm1.front