Rails ActiveRecordのSTI(Single Table Inheritance)の使い方

スポンサーリンク
スポンサーリンク
【お知らせ】 英単語を画像イメージで楽に暗記できる辞書サイトを作りました。英語学習中の方は、ぜひご利用ください!
画像付き英語辞書 Imagict | 英単語をイメージで暗記
【開発記録】
英単語を画像イメージで暗記できる英語辞書サービスを作って公開しました

Rails の STI(Single Table Inheritance)機能を使うと、共通の属性を持つ親クラス(スーパークラス)と、各々独自の属性を持つ子クラス(サブクラス)となるモデルの関係をすっきり表現できます。Martin Fowler 氏のサイトの Single Table Inheritance 説明での例を参考にしました。

P of EAA: Single Table Inheritance

— 環境 —
Rails 4.1.6
activerecord 4.1.6

スポンサーリンク

以下のような継承関係の STI 階層のモデルがあるとして、Player モデルが継承関係で一番上の親クラスとなる。

そして、全てのモデルに共通な属性として :name があり、Footballer に固有な属性として :club があり、Cricketer に固有な属性として :batting_average があり、Bowler に固有な属性として :bowling_average があることになります。STI 利用時のこれらの属性は、テーブルのカラムとしては、全て一つのDBテーブルに格納することとなる(後述する players テーブル)。

以降、上記モデルを実際に作成していき、STI でのモデル操作を試してみました。

type カラムを持つDBテーブルのマイグレーション

まずは、players テーブル用のマイグレーションファイルの作成。

db/migrate/***_create_players.rb

STI を利用する場合は、必ず type カラムを作成するようにします。この type カラムにモデル名が入ります。

マイグレート実行。

モデルのファイルを作成

モデルのファイルでは、継承関係に気をつける。とりあえず動作確認のため、validation などは省略です。

app/models/player.rb(Player モデル)

app/models/footballer.rb(Footballer モデル)

app/models/cricketer.rb(Cricketer モデル)

app/models/bowler.rb(Bowler モデル)

pry(rails console)で動作確認

rails console で動作確認用に適当にいくつかデータを作成します。

この ActiveRecord#create の操作よりレコードが保存され、players テーブルの各レコードの type カラムに、モデル名 ‘Footballer’, ‘Cricketer’, ‘Bowler’ が各々保存されました。players テーブルの type カラムで、レコードがどのモデルのオブジェクトかを判断するわけですね。

続いて、モデルに対する操作で、どのような SQL クエリーが発行されるかを確認してみました。

すごく賢い!親クラスのモデルで検索時は、その子クラスを含めて IN で検索するようになっています。

次に ActiveRecord の find_by を試してみました。

これまた賢い!自動で検索対象となるモデルを type カラムに対して IN で絞り込んで検索しています。

以上、簡単でしたが Rails ActiveRecord の STI(Single Table Inheritance)の使い方でした。Rails やっぱり凄いですね〜、Rails を使ってて久しぶりに便利さに感動しました^^。STI でコントラーラーもひとつにまとめるには、以下クラスメソッドさんのブログ記事が分かりやすいです。

[Rails] STI(Single Table Inheritance)でコントローラも一つに纏める | Developers.IO

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)

Leave Your Message!