class Module # Creates a class instance variable attribute that can # be accessed both on an instance and class level. def mattr( *syms ) writer = false syms.reject! do |s| case s when TrueClass writer = true when FalseClass, NilClass true else false end end if writer mattr_accessor( *syms ) else mattr_reader( *syms ) end end # Creates a class instance variable attr_reader # accessable both on an instance and class level. # # class MyClass # mattr_reader :a # def self.set ; @a = 10 ; end # end # # MyClass.set # MyClass.a #=> 10 # mc = MyClass # mc.a #=> 10 # def mattr_reader( *syms ) hsyms = ( syms.last.is_a?(Hash) ? syms.pop : {} ) hsyms.update( Hash[*(syms.zip([nil]*syms.size).flatten)] ) hsyms.each_pair do |sym, val| class_eval <<-EOS if ! defined? @#{sym} @#{sym} = val end def self.#{sym} @#{sym} end def #{sym} self.class.#{sym} end EOS end return hsyms.keys end # Creates a class instance variable attr_writer # accessable both on an instance and class level. # # class MyClass # mattr_writer :a # def self.show ; @a ; end # end # # MyClass.a = 10 # MyClass.show #=> 10 # m = MyClass.new # m.a = 29 # MyClass.show #=> 29 # def mattr_writer(*syms) hsyms = ( syms.last.is_a?(Hash) ? syms.pop : {} ) hsyms.update( Hash[*(syms.zip([nil]*syms.size).flatten)] ) hsyms.each_pair do |sym, val| class_eval <<-EOS if ! defined? @#{sym} @#{sym} = val end def self.#{sym}=(obj) @#{sym} = obj end def #{sym}=(obj) self.class.#{sym}=(obj) end EOS end return hsyms.keys end # Creates a class instance variable attr_accessor # accessable both on an instance and class level. # # class MyClass # mattr_accessor :a # end # # MyClass.a = 10 # MyClass.a #=> 10 # mc = MyClass.new # mc.a #=> 10 # mc.a = 20 # mc.a #=> 20 # MyClass.a #=> 20 # def mattr_accessor(*syms) m = [] m.concat( mattr_reader(*syms) ) m.concat( mattr_writer(*syms) ) m end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin test require 'test/unit' class TCModule < Test::Unit::TestCase class M def self.setup @a = 10 end # for testing writer def b self.class.instance_eval { @b } end end def setup M.setup end def test_mattr assert_nothing_raised { M.class_eval { mattr :a } } t = M.new assert_equal( 10, M.a ) assert_equal( 10, t.a ) end def test_mattr_reader assert_nothing_raised { M.class_eval { mattr_reader :a } } t = M.new assert_equal( 10, t.a ) end def test_mattr_writer assert_nothing_raised { M.class_eval { mattr_writer :b } } t = M.new t.b = 5 assert_equal( 5, t.b ) end def test_mattr_accessor assert_nothing_raised { M.class_eval { mattr_accessor :c } } t = M.new t.c = 50 assert_equal( 50, t.c ) end end =end