単一テーブル継承(STI)によるモデル設計

アルバム、シングル、ビデオは曲に対して対多な関係にあるなどデータ構造が非常に似通っています。そこで、Album, Single, Video というクラスに対して、これらの共通な親クラス Device を作りました。オブジェクト指向の常として、共通なメソッドについてはこちらに記述すればよくなります。

問題になるのは、ORマッピング先のテーブル構成です。Rails では、これを単一テーブル継承(Single Table Inheritance:STI)という機能で対応します。今回の場合には、devices テーブルにアルバム、シングル、ビデオで使用する属性をすべて詰め込んだ大きなテーブルを作成します。例えば、ライブビデオの撮影日付などは、ビデオにしか関係ありませんが、devices テーブルの中に属性を作ります。また、STI の場合には必ず type 属性が必須であり、ここにはサブクラスの名前が自動的に登録されます。device model は通常通り、以下のようにして作ります。

r g model device type:string j_title:string e_title:string ..... 以下続く

ちなみに r とは bundle exec rails へのエイリアスです。

Album クラスは、generator ではなく、単に Device クラスの子クラスとして作ります。

class Album < Device
  アルバムに依存するメソッドや定数定義のみを記述する
end

差分のみなので、こちらへの記述はかなり少なくなります。Album タイプへの検索は、自動的に Device クラスへの検索となり、自動的に where devices.type = 'Album' の検索条件が付加された SQL が発行されます。

逆に分類わけしたくない場合には、device をそのまま使うことができます。例えば、履歴のページでは、その年に発売されたアルバムやシングルを一括で日付順に出力しています。この場合、年を示す変数 @year に対して、@year.devices.order_date とするだけで済んでしまいます。後は、依存する出力だけを、各クラスで別表記した同一名のメソッドを呼び出すだけです。

P.S.
先月より、セルフカバー 200 曲の YouTube への公開が始まりました。上記に加え、Youtube というクラスを作って登録してみました。サブクラスなのであっという間に作成できました。