chikuchikugonzalezの雑記帳

趣味とか日記とかメモとか(∩゚д゚)

mattr_accessorとcattr_accessor

Rubyの記事を検索して出てくるページにですね、モジュールに対するattr_accessorみたいな関数であるmattr_accessorというのがあったのですよ。
で、それを使おうとしたら

そんなんしらんわ(´・ω・`)

的なことをRubyインタプリタさんは言ってくるわけですよ。

色々Googleさんに聞いたらどうもこれ、Rails (てかActiveSupport) で定義されているらしい。ので、それをRailsなしでも動くやつとして抜き出してみた*1

まずはModuleのmattr_accessorから。正直class_evalとか初めて見たわ(;´∀`)

class Module
  def mattr_reader(*syms)
    syms.each do |sym|
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        @@#{sym} = nil unless defined?(@@#{sym})
        def self.#{sym}()
          return @@#{sym}
        end
      EOS
    end
  end
  def mattr_writer(*syms)
    syms.each do |sym|
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def self.#{sym}=(obj)
          @@#{sym} = obj
        end
      EOS
    end
  end
  def mattr_accessor(*syms)
    mattr_reader(*syms)
    mattr_writer(*syms)
  end
end

ほんでこっちがclass用のcattr_accessor。Moduleクラスを拡張するかclassクラスを拡張するかの違いしか無いだろうと

class Class
  def cattr_reader(*syms)
    syms.each do |sym|
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        @@#{sym} = nil unless defined?(@@#{sym})
        def self.#{sym}()
          return @@#{sym}
        end
      EOS
    end
  end
  def cattr_writer(*syms)
    syms.each do |sym|
      class_eval(<<-EOS, __FILE__, __LINE__ + 1)
        def self.#{sym}=(obj)
          @@#{sym} = obj
        end
      EOS
    end
  end
  def cattr_accessor(*syms)
    cattr_reader(*syms)
    cattr_writer(*syms)
  end
end

*1:ソースコードが隠蔽できないっていいよね