ActiveRecordの設計
ActiveRecordはRailsの一部であり、Rubyのオブジェクトをデータベースのテーブルにマッピングするものである。この機能をオブジェクトリレーショナルマッピングと呼ぶ。
ActiveRecordはRailsアプリケーションでは、モデル(MVCの「M」)として使われる。通常のRubyのオブジェクトでビジネスロジックを管理し、ActiveRecordでオブジェクトをデータベースに永続化することになる。
ActiveRecordの簡単な例
1 2 3 | |
上記の例では、6文字より長いnameをデータベースに保存しようとすると、例外を発生するか(save!の場合)、何も言わずに失敗する(saveの場合)。
ActiveRecordは規約に基づいて、自動的にDuckクラスをducksテーブルにマッピングしてくれる。データベーススキーマからducksテーブルにnameが含まれることを認識し、属性にアクセスするゴーストメソッドを定義する。
1 2 3 4 5 6 7 8 9 10 | |
のように使われる。
ActiveRecord::Base
1 2 3 4 5 6 7 8 9 10 | |
ActiveRecordはautoload()を使って各モジュールを読み込んでいる。Kernel#autoload()はモジュール名とファイル名を受け取り、モジュールを最初に参照した時にファイルを自動的に読み込む。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
ActiveRecord::Baseには上記のコードのようにクラスメソッド、インスタンスメソッドを定義している。
ActiveRecord::Validations
先ほど使ってたvalid?()やvalidates_length_of()などのメソッドはActiveRecord::Validationsモジュールで定義されている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
ActiveRecord::BaseはActiveRecord::Validationsをインクルードしていて、さらにフックメソッドを通してクラスメソッドも手に入れている。これはクラス拡張ミックスインである。ActiveRecord::Baseはモジュールのインクルードを繰り返して、メソッドを積み上げていく。
alias_method_chain()
1 2 3 4 5 6 7 | |
例えば、このgreetメソッドの周りにロギング機能をつけたいとする場合、アラウンドエイリアスを使えば良い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
このような仕組みをRailsではModule#alias_method_chain()を使って使用できる。これはActiveSupportライブラリで提供されている。
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
上記のコードではActiveRecord::Baseクラスを再オープンして、save()とsave!()に検証機能をつけている。これでオブジェクトをデータベースに保存した時に自動的に検証を行ってくれる。
ActiveRecordのまとめ
ActiveRecord::BaseはActiveRecordのメインとなるクラスだ。インスタンスメソッドとクラスメソッドが定義されているが、それ以外にもActiveRecord::Validationsのような追加モジュールをインクルードしている。モジュールをインクルードする際、クラス拡張ミックスインをして、さらに別のモジュールをインクルードする。こうしたモジュールはalias_method_chain()を使ってさらにいろんなメソッドを生み出す。このように次々にメソッドが定義されて、ActiveRecord::Baseは巨大なクラスになっていく。