はじめに
実装をしているときにKlass
という言葉がでてきました
それをきっかけにinclude
周りで何をしているのかというところを理解したので軽くまとめていきます
問題
以下のようなコードがありました
class Companies::SampleController < ApplicationController
include Mixins::TestController
module Mixins::TestController
module InstanceMethods
def load_example
(省略)
def self.included klass
klass.send :include, InstanceMethods
method_name = case klass.name
when 'HogeContRoller' then :load_hoge
when 'FugaController' then :load_fuga
else :load_other
end
klass.before_filter method_name
end
end
ここでsample_controller
がMixins::TestController
を読み込んでいるのはわかったのですが、そこで
def self.included klass
というのをやっておりそこからよくわからなくなりました
解決方法
def self.included
をすると、include
がsample_controller.rb
で呼ばれた段階で、発火するようになります
そしてklass
というのをがありますが、これは単に変数名でclass
というのが予約後なために使っているものでした
klass
にはinclude
したコントローラーの情報が渡ってくるため、klass.name
でコントローラー名で処理を変えることができます(whenの部分)
lass.send :include, InstanceMethods
この部分ですが、InstanceMethods
は上に書いてある
module InstanceMethods
def load_example
この部分を表しており、このモジュールをさらにinclude
するようにしています。
klass.send
としているのはプロテクトがされているためそれを突破するためにsendを利用して親であるsample_controller
でInstanceMethods
を利用できるようにしていています(includeできるようにしています)
最後に
klass.before_filter method_name
をすることでコントローラーごとにbefore_filter
するものを設定して、include
するだけで自動的にbefore_filter
が行われるようになります
おわりに
なぜかコントローラーでbefore_filter
していないのにインスタンスが使えるよいうになっていて不思議に思いましたが、このようなからくりがありました
Ruby自体の仕組みを勉強することがなかったのですが、とても面白いなと感じました