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
は巨大なクラスになっていく。