Rubyのクラスはオブジェクト
Rubyの復習の続き。
attr_accessorみたいに、クラス定義の中で呼ばれているメソッドのレシーバは何かというと、その定義しているクラス自身になる。Rubyではこれもオブジェクトだからだ。このオブジェクトはどのクラスから生成されているかというと、Classクラスであり、そのClassクラスはModuleクラスを継承している。
クラス定義中も実際にRubyの処理が実行中のため、attr_accessorがコールされると、レシーバはその定義しているクラス自身になる。こいつにはattr_accessorメソッドが存在しないため、親クラスであるClassクラスに処理が渡され、さらに親のModuleクラスに渡されてそこで処理されることになる。
クラス自身がレシーバということだけど、それはクラス名という形で表現されている。クラス名がクラスのオブジェクトを表している。だからクラスメソッドの定義とはつまり、クラスオブジェクト(これもインスタンスだ)の特異メソッドとイコールになる。ふむふむ。このあたりのことはなんとなくどこかで読んだ覚えはあるのだけど、ちゃんと理解していなかったね。
2007年10月20日の日記のSpoonモジュールだけど、set_jump_urlメソッドをModuleクラスのインスタンスメソッドに追加定義しているので、どのクラスでも使えてしまう。それにModuleクラスみたいな根幹クラスにメソッド追加するのはあまりよろしくない。
上記の理解をもとに考えると、ひとつのコントローラ限定で使用したいときは、そのコントローラのクラスメソッドに定義してやればいいことになる。
module Spoon
...(省略)...
def self.included(base)
def base.set_jump_url(args)
return unless (args.kind_of? Hash) || (args.kind_of? String)
define_method :jump_url do
args
end
private :jump_url
end
end
end
ポイントは def base.set_jump_url(args) のところ。これでこのモジュールをincludeしたクラスのクラスメソッドに、set_jump_urlを追加定義してやることになる。
あと、重要なのが private :jump_url のところ。これがないとアクションとしてjump_urlにアクセスできてしまうので注意。
このときのjump_urlは、呼出し元のクラス固有のものになるのでクラスが異なれば違う値となる。