There have been many attempts to rewrite attr_accessor to support default values; the best attempt so far (in my opinion) is schmidt’s ‘attr_accessor on steroids’. attr++ is an extension of schmidt’s work to support the initialization of multiple attributes on a single line. The syntax is as follows:
attr_plus_plus {x 20; y "hello"; z 1, 2, 3}
The code above defines getters and setters for the x, y and z attributes and initializes them to the values 20, “hello” and [1, 2, 3] respectively.
attr++ also suppots the old attr_accessor syntax, and you may mix it along with the new attr++ syntax on the same line:
attr_plus_plus :a, :b, :c {a 10; b "goodbye"; z}
In the above, attributes ‘a’ and ‘b’ are initialized to 10 and “goodbye” respectively, and attributes ‘c’ and ‘z’ are unitialized.
The sourcecode for attr++ is given below:
module Attr_plus_plus
def attr_plus_plus(*argv, &block)
defaults = {}
proxy = Object.new
eigen = class << proxy; self; end
eigen.send(:define_method,:method_missing) { |name, *argvt|
defaults[name] = argvt.size > 1 ? argvt : argvt.first
}
proxy.instance_eval &block
defaults.each_pair { |name, default_val|
attr_writer(name)
define_method(name) do
class << self; self; end.class_eval do
attr_reader( name )
end
if instance_variable_defined? "@#{name}"
instance_variable_get( "@#{name}" )
else
instance_variable_set( "@#{name}", default_val )
end
end
}
(argv-defaults.keys).each { |name|
raise ArgumentError if !(Symbol === name)
attr_accessor name
}
end
end
UPDATE: I no longer consider attr++ a good solution.
Filed under: metaprogramming, programming, ruby | Tagged: attr_accessor, attr_accessor default values, dsl, meta-programming, ruby