【Rails】ActiveRecord:単一テーブル継承(sti)とポリモーフィック関連を未だにぱっと思い出せないのでまとめ。
ActiveRecordで単一テーブル継承(STI:Single Table Inheritance)とポリモーフィック関連という2つの便利なモデルの持ち方?関係性?があるのですが、恥ずかしながらいつも混同してしまいます…
多分頭の中では両方とも「似たモデルをまとめる」みたいなぼんやりした認識してるので混ざってしまっているようで…
すごい今更ですが
ちょっと自分なりにまとめてみようと思います。
単一テーブル継承(STI:Single Table Inheritance)
同じような機能(メソッド)を持つActiveRecordモデルクラスが2つ存在するので、
継承を使って実装しようとした場合。
例として
「Information」モデルを継承した「Warning」クラスと「Notice」クラスを作成するとします。
(例としておかしかったらごめんなさい…)
単純に実装すると、各モデルに対しDBのテーブルが作成されるのですが、
STIではInformationテーブルのみを使用して実装することができます。
モデルの定義はこんな感じ。
class Information < ActiveRecord::Base … end class Warning < Information … end class Notice < Information … end
で、例えばWarningオブジェクトをsaveすると、Informationテーブルにtype:Warningとして保存されます。
Noticeならtype:Noticeに。
それぞれのモデルからデータへの操作を行った場合、適合するTypeのデータのみを操作対象とします。
両方をまとめて扱いたい場合(WarningもNoticeも関係なく取得したいとか)は、
Informationモデルから操作すればOKだと思います多分。
当然ひとつのテーブルを使っていますので、片方にしか無い項目(カラム)もテーブルに含まなければなりません。
例えばWarningとNoticeの持つ項目があまりにも違う場合、カラム数すげー増えます。
あまりないと思いますけど。
〜参考にさせていただきました!〜
Railsで単一テーブル継承(Single Table Inheritance) - 京の路
ポリモーフィック関連(polymorphic)
ココ見りゃいいって話ではありますが…
〜参考にさせていただきました!〜
Active Record Associations — Ruby on Rails Guides
ruby/rails/RailsGuidesをゆっくり和訳してみたよ/Active Record Associations - 株式会社ウサギィwiki
例えばアプリケーションなんかで、CompanyモデルとUserモデルを持っていたとします。
両方とも画像モデルクラス(会社の写真、ユーザーのプロフィール写真)と関連しているのですが、
持っている項目が全く同じなので一つのモデルとして管理したい場合、ポリモーフィック関連で実装できます。
モデルの定義はこんな感じ。
class Image < ActiveRecord::Base belongs_to :imageable, :polymorphic => true end class Company < ActiveRecord::Base has_many :images, :as => :imageable end class User < ActiveRecord::Base has_many :images, :as => :imageable end
こうすることでTypeによって紐付く親が判別されるので、UserやCompanyモデルから自身に関係するImageが取得できます。
親モデルが新たに増えたとしても、has_manyの関連を定義してやるだけでImageモデルが利用できるわけですね。
とか書きましたがすごく丁寧に解説されている記事が…
〜すごく参考にさせていただきました!〜
2010-06-19 - 篳篥日記
おすすめ!
ただ疑問なのが、imageのエイリアス?としてimageableと付けること…
なんかしっくりこない。
ポリモーフィック関連の例を見てると大体〜ableってつけてるみたいなんですよね。。
…確かに親IDを格納するカラムがImage_idだとおかしい気もしますが、
imageable_idとかimageable_typeとかもピンとこないような…