モデルを豊かにする仕組み
モデルの関係(アソシエーション)
Rails におけるアソシエーション
- has_many
- 親となるモデルから見て、異なるモデルとの関係が1対多のときに使用する
- has_one
- 親となるモデルから見て、異なるモデルとの関係が1対1のときに使用する
- belongs_to
- 子となるモデルが、親モデルに所属する関係を持つ時に使用する
- 関係を紐づけるためには外部キーが必要
- 親モデル_id(タイプはinteger)を設定することで外部キー属性として見なしてくれる
- 親モデル名(タイプはreference)という属性を指定することもできる
多対多の関係
- hmt型
- has_manyメソッドのthroughオプション
- 直接多対多の関係ではなく双方に関連する子モデルが存在する
has_many :models, through: :childs
- habtm型
- has_and_belongs_to_many メソッドを使用する方法
- 仲介、結合のためのテーブルを作成し、それを利用して関係付けていく
- この中間テーブルは対応するモデルを持たないテーブル
- BookモデルとUserモデルの中間テーブルの結合名はbooks_usersのようになる
アソシエーションメソッドのオプション
- class_name
- アソシエーションのメソッド名をモデルと異なる名前で利用したい場合に、実装のモデル名を対応づけるオプション
- dependent
- 親子関係のモデルで、親を削除する際に子をどう扱うか指定するオプション
- :destroy
- :restrict_with_error
- 子のデータリソースがある場合親のインスタンスにエラー通知を出す
- :restrict_with_exception
- :delete
- 紐づいたデータリソースをデータベースから直接削除する
- コールバックは実行されない
- nullify
- 親のリソースが削除された時に子モデルの外部キーがnullになる
- foreign_key
- 子モデルに設定する親モデルの外部キーは親モデル_idになる
- 子のオプションを指定することで別の名前に対応づけることができる
- association_foreign_key
- has_and_belongs_to_manyで自己結合モデルを実現する時に foreign_key と組み合わせることでシンプルに記述できる
class Person < ApplicationRecord
has_and_belongs_to_many :friends,
class_name: "Person",
foreign_key: "self_person_id",
association_foreign_key: "other_person_id"
end
class CreatePeoplePeople < ActiveRecord::Migration[5.2]
def change
create_table :people_people do |t|
t.references :self_person, index: true
t.references :other_person, index: true
end
end
end
- 外部キーの指定で必ず index: true を指定する必要がある
- autosave
- 親インスタンスを保存した時にその時点で紐づいている子のインスタンスも全て保存される
- 子モデルのアソシエーション設定に対してtrueにすると子モデルを保存した時に親モデルも保存される
- validate
- アソシエーションを設定している親子モデルにおいて、バリデーションも合わせて実行するか設定できる
単一テーブル継承
- データベースの1つのテーブルに対応するモデルをもとにして、複数の異なるモデルに継承させる単一テーブル継承という関係がある
- 同じような情報を持つ目的別の複数モデルを一つのテーブルだけで対応させることができる
- 対象のモデルは異なるのでそれぞれのモデルで個別のバリデーションなどの処理を行える
- ex.ペットモデルを継承する犬モデルor猫モデル
- ペットモデルのデータはtypeフィールドを持っており、継承されるモデルのクラス名が保存される
モデル結合を利用したインスタンス配列の取得
- モデル結合とは、関係する複数のデータリソースを1つのモデルのデータリソースのように取り扱う方法
- 左外部結合
- 結合メソッドを呼び出したインスタンスのテーブルのデータを基準に相手方のテーブルの外部キーidで結合する
- 内部結合
- お互いに外部キーで紐づくidの一致するリソースを結合する
- 結合メソッド
- joins
- left_outer_joins, left_joins
- includes
- joinsメソッドと異なりモデル間にまたがる処理で発生するN+1問題を解決する手段として有効
- INNER JOIN を使用せずに結合するモデルの対応リストを作成し、それをもとにデータを取得する
- N + 1問題はテーブルに対するn件のデータを検索する場合に、n+1件の検索命令(SELECT)が発行されてしまう問題
仮想的な属性(Attributes API)
タイプオブジェクト
- 標準の属性型ではないカスタマイズ属性型を提供するためのオブジェクト