Railsドキュメント

参照元テーブルから参照先テーブルを参照

説明

参照元テーブルから参照先テーブルを参照するための設定

使い方

belongs_to(関連モデル名 [, scope, オプション])

オプション

オプション 説明 デフォルト値
:class_name 関連を設定するモデル名を指定。関連名と参照先のクラス名を異なるものにしたい場合に指定  
:foreign_key 参照先を参照するための外部キーの名前を指定 :foreign_key
:foreign_type 参照先を参照するための外部キーの型を指定 :foreign_type
:primary_key 主キーを指定 id
:dependent 値を:destroyにすると、参照先が削除される場合に参照元もDBから削除  
:counter_cache カウンタキャッシュを使用するか  
:polymorphic ポリモーフィック関連を定義  
:validate 関連オブジェクトのバリデーションの有無 false
:autosave 親のオブジェクトが保存されると、ロードされたオブジェクトも保存するか  
:touch updated_atまたはupdated_onが保存または破棄された場合に現在の時刻を設定するか  
:inverse_of モデルを指定  
:optional 関連付けの確認は行わないか?  
:required 関連付けの確認するか? true
:default 特定のカラムの初期化  

追加されているメソッド

メソッド 説明
association=(associate) 引数を参照元オブジェクトとして設定。それ以外の参照元との関連は破棄
build_association(attributes = {}) 新しいオブジェクトを生成。引数にはオブジェクトを生成するのに必要なパラメータを指定。この時点では保存されない
create_association(attributes = {}) 新しいオブジェクトを生成して保存。引数にはオブジェクトを生成するのに必要なパラメータを指定
create_association!(attributes = {}) 新しいオブジェクトを生成して保存。引数にはオブジェクトを生成するのに必要なパラメータを指定。失敗時に例外を発生
reload_association キャッシュではなくデータベースから直接値を取得

保存

参照元オブジェクトが未保存の場合

  • saveのタイミングで外部キーが設定され保存
  • 参照先オブジェクトが未保存であれば、saveのタイミングで自動的に保存

参照元オブジェクトが保存済みの場合

  • 保存済みの場合には、生成したタイミングで自動的にDBに保存

UserとProjectの関係

基本的な使い方
belongs_to :user

クラス名としてUserを指定

belongs_to :admin_user, class_name: "User"

user_id = 2を抽出

belongs_to :user, conditions: "user_id = 2"

逆順で並び替える

belongs_to :user, order: "id DESC"

データを削除するときに関連するテーブルを削除

belongs_to :user, dependent: :destroy

外部キーを指定

belongs_to :user, foreign_key: "blog_id"

特定のキーの初期化

belongs_to :account, default: -> { company.account }

ソースコード

* [GitHub](https://github.com/rails/rails/blob/f33d52c95217212cbacc8d5e44b5a8e3cdc6f5b3/activerecord/lib/active_record/associations.rb#L1657)

1対1の関連を宣言

説明

別のモデルとの1対1の関連付けを指定

使い方

has_one(関連モデル名 [, scope ,オプション])

オプション

オプション 説明
:class_name 関連名と参照元のクラス名を異なるものにしたい場合に指定
:dependent 値を:destroyにすると、参照先が削除される場合に参照元もDBから削除
:foreign_key 関連で使用する外部キー名
:foreign_type オブジェクトタイプを指定
:primary_key 参照先のテーブルに定義されている外部キーの名前を指定
:as ポリモーフィック関連を定義
:through 結合モデルの指定
:source has_one :throughの元となるオブジェクトを指定
:source_type polymorphicの指定
:validate オブジェクトが保存されると、バリデイトが実行される
:autosave 親のオブジェクトが保存されると、ロードされたオブジェクトも保存
:inverse_of モデルを指定
:required 関連先オブジェクトが存在するかバリデーション

追加されるメソッド

メソッド 説明
association(force_reload = false) 自分自身を参照しているオブジェクトを返す。オブジェクトが無い場合は、nilを返す
association=(associate) 引数を参照元オブジェクトとして設定。それ以外の参照元との関連は破棄
build_association(attributes = {}) 新しいオブジェクトを作成。引数にはオブジェクトを生成するのに必要なパラメータを指定。この時点では保存されない
create_association(attributes = {}) 新しいオブジェクトを作成して保存。引数にはオブジェクトを生成するのに必要なパラメータを指定
create_association!(attributes = {}) 新しいオブジェクトを作成して保存。引数にはオブジェクトを生成するのに必要なパラメータを指定。エラー時に例外を発生
reload_association リロード

保存

参照先オブジェクトが未保存の場合

  • saveのタイミングで外部キーが設定され保存
  • 参照先オブジェクトが未保存であれば、saveのタイミングで自動的に保存

参照先オブジェクトが保存済みの場合

  • 保存済みの場合には、作成するタイミングで自動的にDBに保存

UserとProjectの関係

マイグレーションファイル
class CreateUsersProjectsTable < ActiveRecord::Migration
  def self.up
    create_table :users_projects, id: false do |t|
      t.integer :user_id
      t.integer :project_id
    end
  end
  def self.down
    drop_table :users_projects
 vend
end
Userモデル
class User < ActiveRecord::Base
  has_one :project
end
Projectモデル
class Project < ActiveRecord::Base
  belongs_to :user
end

クラス名としてUserを指定

has_one :admin_user, class_name: "User"

user_id = 2を抽出

has_one :user, conditions: "user_id = 2"

逆順で並び替える

has_one :user, order: "id DESC"

データを削除するときに関連するテーブルを削除

has_one :user, dependent: :destroy

外部キーを指定

has_one :user, foreign_key: "blog_id"

ソースコード

1対多の関連を宣言

説明

1対多や多対多の関連付けを指定

使い方

has_many(関連モデル名 [, scope, オプション])

オプション

オプション 説明
:class_name 関連名と参照元のクラス名を異なるものにしたい場合に指定
:foreign_key 参照元のテーブルに定義されている外部キーの名前を指定
:foreign_type オブジェクトタイプを指定
:primary_key 参照先のテーブルに定義されている外部キーの名前を指定
:dependent 値を:destroyにすると、参照先が削除される場合に参照元もDBから削除
:counter_cache カウンターキャッシュ
:as ポリモーフィック関連を定義
:through 結合モデルの指定
:source has_one :through の元となるオブジェクトを指定
:source_type polymorphicの指定
:validate オブジェクトが保存されると、バリデイトが実行される
:autosave 親のオブジェクトが保存されると、ロードされたオブジェクトも保存
:inverse_of モデル名を指定
:extend 関連を拡張

追加されるメソッド

メソッド 説明
collection(force_reload = false) 関連付けられている配列
collection«(object, …) collectionにobjectを追加
collection.delete(object, …) 1つ以上のobjectを削除
collection.destroy(object, …) 1つ以上のobjectを削除
collection=objects 多対多でひも付いたモデルを更新
collection_singular_ids 関連付けられているオブジェクトのIDの配列
collection_singular_ids=ids 主キーを切り替える
collection.clear すべて切断
collection.empty? オブジェクトが関連付けられていなければtrue
collection.size サイズ
collection.find(…) 通常のfindメソッド
collection.exists?(…) 与えられた条件に一致するモデルが存在するか確認
collection.build(attributes = {}, …) 新しいモデルを作り、多対多で関連付けるがDBは更新しない
collection.create(attributes = {}) 新しいモデルを作り、多対多で関連付けてDBを更新
collection.reload リロード

保存

参照先オブジェクト、参照元オブジェクトのどちらかが未保存の場合

  • saveのタイミングで両方とも保存

参照先オブジェクト、参照元オブジェクトの保存済みの場合

  • 参照元オブジェクトの外部キーが更新され、保存

UserとProjectの関係

マイグレーションファイル
class CreateUsersProjectsTable < ActiveRecord::Migration
  def self.up
    create_table :users_projects, id: false do |t|
      t.integer :user_id
      t.integer :project_id
    end
  end
  def self.down
    drop_table :users_projects
  end
end
Userモデル
class User < ActiveRecord::Base
  has_many :projects
  accepts_nested_attributes_for :projects
end
Projectモデル
class Project < ActiveRecord::Base
  belongs_to :user
  accepts_nested_attributes_for :user
end

クラス名としてUserを指定

has_many :admin_user, class_name: "User"
accepts_nested_attributes_for :admin_user

user_id = 2を抽出

has_many :user, conditions: "user_id = 2"
accepts_nested_attributes_for :user

逆順で並び替える

has_many :user, order: "id DESC"
accepts_nested_attributes_for :user

Group

has_many :users, group: "category"
accepts_nested_attributes_for :users

外部キーを指定

has_many :user, foreign_key: "blog_id"
accepts_nested_attributes_for :user

ソースコード

多対多の関連を宣言

説明

多対多の関連付けを指定

使い方

has_and_belongs_to_many(関連モデル名 [, scope, オプション])

オプション

オプション 説明
:class_name 関連モデルのクラス名を指定。関連モデル名から推測できない場合のみ指定
:join_table 結合テーブルの名前を指定
:foreign_key 多対多の関連で使用する外部キーの名前を指定
:association_foreign_key 多対多の関係で関連先への外部キーを指定
:validate 現在のモデルを保存する場合、関連先のバリデーションを実行
:autosave 親モデルに合わせて、保存や削除

使えるようになるメソッド

メソッド 説明
collection(force_reload = false) 多対多でひも付いた先のモデルである一覧を取得
collection«(object, …) 1つ以上のモデルを多対多の関連に追加
collection.delete(object, …) 1つ以上のモデルを多対多の関連から外す
collection.destroy(object, …) 1つ以上のモデルを多対多の関連から外す
collection=objects 多対多でひも付いたモデルを更新
collection_singular_ids 多対多でひも付いたモデルのidの配列を取得
collection_singular_ids=ids 多対多でひも付いたモデルのidが指定された物に更新
collection.clear 多対多の関連をすべて削除
collection.empty? 多対多の関連にあるモデルが1つもないときにtrue
collection.size 多対多でひも付いたモデル数を取得
collection.find(id) 多対多の関連モデルでfindを実行
collection.exists?(…) 与えられた条件に一致するモデルが存在するか確認
collection.build(attributes = {}) 新しいモデルを作り、多対多で関連付けるがDBは更新しない
collection.create(attributes = {}) 新しいモデルを作り、多対多で関連付けてDBを更新
collection.reload リロード

UserとProjectの関係

マイグレーションファイル
class CreateUsersProjectsTable < ActiveRecord::Migration
  def self.up
    create_table :users_projects, id: false do |t|
      t.integer :user_id
      t.integer :project_id
    end
  end
  def self.down
    drop_table :users_projects
  end
end
Userモデル
class User < ActiveRecord::Base
  has_and_belongs_to_many :projects
end
Projectモデル
class Project < ActiveRecord::Base
  has_and_belongs_to_many :users
end

ソースコード

ポリモーフィック関連

説明

  • belongs_to宣言に:polymorphicオプションを指定すると、ポリモーフィック関連になる
  • 参照先となるモデルをあらかじめ定義せず、参照元となるオブジェクトごとに指定する関連

使い方

  • 参照元となるモデルに対応するテーブルに、参照先のIDと参照先クラスを指定するカラムをそれぞれ生成
  • 参照先のIDを保存するカラムは「belongs_to宣言で渡す関連名_id」
  • 参照先クラスを指定するカラムは「関連名type」

ポリモーフィック関連を利用するマイグレーションファイルの生成
$ rails generate model AttachmentImage attachable_id:integer attachable_type:string

class CreateAttachmentImage < ActiveRecord::Migration
  def self.up
    create_table :attachment_images do |t|
      t.integer :attachable_id
      t.string :attachable_type

    t.timestamps
  end
end
ボリモーフイツク関連を利用する宣言
class AttachmentImage < ActiveRecord::Base
  belongs_to :attachable, polymorphic: true
end

class Blog < ActiveRecord::Base
  has_many :entries
  has_one :attachment_image, as: :attachable
end

class Entry < ActiveRecord::Base
  belongs_to :blog
end

def self.down
  drop_table :attachment_images
end

カウンターキャッシュ

説明

子モデルの数を親モデルのカラムに保存

概要

  • デフォルトを0
  • カラム名は、子モデルのテーブル名_countがおすすめ

使い方

belongs_to(:親モデル, counter_cache: 親モデルのカラム)

Commentの登録や削除で、comments_countが自動更新

def self.up
  add_column :entries, :comments_count, :integer, default: 0
end

belongs_to :entry, counter_cache: :comments_count