ARの構造をみてみる続き

自分でActiveRecord::BaseクラスやValidationsモジュールの簡易版を書いて
動かして、なんとなく分かってきた気がする。



ActiveRecord::BaseクラスでValidationsなどのmoduleをextendすると

ValidationsのインスタンスメソッドはBaseクラスのクラスメソッドとしてしか使えなくなってしまう。



ActiveRecord::BaseクラスでValidationsなどのmoduleをふつうにincludeすると

ValidationsのインスタンスメソッドはBaseクラスのインスタンスメソッドとしてしか使えなくなってしまう。



moduleのインスタンスメソッドをBaseクラスのクラスメソッドとインスタンスメソッドの両方ともに適用したかったら

moduleはincludeするようにして、include時に実行されるmoduleのメソッド(self.append_features)にて
クラスメソッドとしてBaseクラスに追加したいやつ、インスタンスメソッドとして追加したいやつってのを
設定するのがCool!っていうか定石ってことなのかな。
そうなのですか?トライの先生!




また、さらにBaseクラスにインスタンスメソッドとして追加するときに
alias_methodを使って既存メソッドの置き換えをやってる。
validations.rbではこんなコードになっている。勝手にコメントつき。

validations.rb
 module Validations
   def self.append_features(base) # :nodoc:
   #baseはActiveRecord::Base
     
     super
   #ClassMethodsモジュールのメソッドを
     #クラスメソッドとして追加
     base.extend ClassMethods
     
   #Validationsモジュールのメソッドを
     #インスタンスメソッドとして追加
     base.class_eval do
       alias_method :save_without_validation, :save
       alias_method :save, :save_with_validation
 
       alias_method :update_attribute_without_validation_skipping, :update_attribute
       alias_method :update_attribute, :update_attribute_with_validation_skipping
     end
   end

   #Baseクラスにクラスメソッドで追加したいやつら
   module ClassMethods
     def hoge
     ・・・
     end  
  ・・・
   end 

   #Baseクラスにインスタンスメソッドで追加したいやつら
   def bar
     ・・・
   end
  ・・・
 end

既存メソッドのsaveをsave_without_validationに置き換えて、
Validationsモジュールで定義しているsave_with_validationを
saveにしている。

save_with_validationメソッドはこんなことになっている。

validations.rb
def save_with_validation(perform_validation = true)
  if perform_validation && valid? || !perform_validation
    save_without_validation
   else
    false
    end
end

こんな感じでラップしていくのであろう。
いいのかな?トライの先生!


なんかでもModuleとかClassとかちゃんとわかってないなあ。


たのしいRuby 第2版 Rubyではじめる気軽なプログラミング
たのしいRuby 第2版 Rubyではじめる気軽なプログラミング高橋 征義 後藤 裕蔵

ソフトバンククリエイティブ 2006-08-05
売り上げランキング : 1835


Amazonで詳しく見る
by G-Tools