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ではじめる気軽なプログラミング | |
高橋 征義 後藤 裕蔵 ソフトバンククリエイティブ 2006-08-05 売り上げランキング : 1835 Amazonで詳しく見る by G-Tools |