#-- # Credit goes to DHH. #++ class Module # Creates a class-variable attr_reader that can # be accessed both on an instance and class level. # # class MyClass # @@a = 10 # cattr_reader :a # end # # MyClass.a #=> 10 # MyClass.new.a #=> 10 # def cattr_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-variable attr_writer that can # be accessed both on an instance and class level. # # class MyClass # cattr_writer :a # def a # @@a # end # end # # MyClass.a = 10 # MyClass.a #=> 10 # MyClass.new.a = 29 # MyClass.a #=> 29 # def cattr_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-variable attr_accessor that can # be accessed both on an instance and class level. # # class MyClass # cattr_accessor :a # end # # MyClass.a = 10 # MyClass.a #=> 10 # mc = MyClass.new # mc.a #=> 10 # def cattr_accessor(*syms) m = [] m.concat( cattr_reader(*syms) ) m.concat( cattr_writer(*syms) ) m end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin test require 'test/unit' class TCModule < Test::Unit::TestCase class MockObject def initialize @@a = 10 end def b ; @@b ; end end def test_cattr_reader assert_nothing_raised { MockObject.class_eval { cattr_reader :a } } t = MockObject.new assert_equal( 10, t.a ) end def test_cattr_writer assert_nothing_raised { MockObject.class_eval { cattr_writer :b } } t = MockObject.new t.b = 5 assert_equal( 5, t.b ) end def test_cattr_accessor assert_nothing_raised { MockObject.class_eval { cattr_accessor :c } } t = MockObject.new t.c = 50 assert_equal( 50, t.c ) end end =end