LoginSignup
62
47

More than 3 years have passed since last update.

【Rails】Associationメソッドまとめ

Last updated at Posted at 2019-03-12

概要

Ruby on Railsでよく使用されるAssociationsの簡単な説明、よく使用されるメソッドをまとめました。

本記事で扱うAssociations

  • One to One
  • One to Many
  • Many to Many(has_many_through)
  • Many to Many (has_and_belongs_to_many)
  • Plymorphic One to Many

One to One

One to Oneはモデル同士に「1対1」関係がある事を示す。
モデルAの1つのレコードがモデルBの1つのインスタンスを丸ごと所有している。
例えば、1人のユーザーが1つのプロファイルを持つ場合。

各テーブルのカラム

# CreateUsers
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.timestamps
    end
  end
end

# CreateProfiles
class CreateProfiles < ActiveRecord::Migration[5.1]
  def change
    create_table :profiles do |t|
      t.string :name
      t.references :user
      t.timestamps
    end
  end
end

各モデル

# app/models/user.rb
class User < ApplicationRecord
  has_one :profile
end

# app/models/profile.rb
class Profile < ApplicationRecord
  belongs_to :user
end

One-to-Oneで頻繁に使用されるメソッド

user.profile :該当ユーザーのプロファイル情報を取得
user.build_profile :該当ユーザーのプロファイルを作成(DBに保存しない)
user.create_profile :該当ユーザーのプロファイルを作成(DBに保存する)

One-to-Many

One-to-Manyは他のモデルとの間に「1対多」の関係がある事を示す。
モデルAの1つのレコードが0個以上のモデルBのインスタンスを所有している。
例えば、1人のユーザー(user)が複数の投稿(post)を持つ場合。

各テーブルのカラム

# CreateUsers
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.timestamps
    end
  end
end

# CreatePosts
class CreatePosts < ActiveRecord::Migration[5.1]
  def change
    create_table :posts do |t|
      t.string :title
      t.references :user
      t.timestamps
    end
  end
end

各モデル

# app/models/user.rb
class User < ApplicationRecord
  has_many :posts
end


# app/models/profile.rb
class Post < ApplicationRecord
  belongs_to :user
end

One-to-Manyで頻繁に使用されるメソッド

user.posts :該当ユーザーの全ての投稿を取得。
user.posts << post :新しい関係を作成する。
user.posts.build({}) :該当ユーザーの投稿を作成する。(DBに保存しない)
user.posts.create({}) :該当ユーザーの投稿を作成する。(DBに保存する)
post.build_user :ユーザー作成。(DBに保存しない)
post.create_user :ユーザー作成。(DBに保存する)

Many to Many(has_many_through)

Many-to-Manyは他のモデルとの間に「多対多」の関係がある事を示す。
モデルAとモデルB共に相互の複数のインスタンスを所有している。
has_many_throughの方式ではモデルC(結合モデル)がモデルAとモデルBを繋ぐ。
例えば、複数の投稿(post)が複数のタグ(tag)を持つ場合。

各テーブルのカラム

# CreatePosts(モデルA)
class CreatePosts < ActiveRecord::Migration[5.1]
  def change
    create_table :posts do |t|
      t.string :title
      t.timestamps
    end
  end
end

# CreateTags(モデルB)
class CreateTags < ActiveRecord::Migration[5.1]
  def change
    create_table :tags do |t|
      t.string :name
      t.timestamps
    end
  end
end

# CreateTaggings(モデルC)
class CreateTaggings < ActiveRecord::Migration[5.1]
  def change
    create_table :taggings do |t|
      t.references :tag
      t.references :post
      t.timestamps
    end
  end
end

各モデル

# app/models/post.rb
class Post < ApplicationRecord
  has_many :taggins
  has_many :tags, through: :taggings
end

# app/models/tag.rb
class Tag < ApplicationRecord
  has_many :taggins
  has_many :posts, through: :taggings
end

# app/models/tagging.rb
class Tagging < ApplicationRecord
  belongs_to :tag
  belongs_to :post
end

Many-to-Many(has_many_through)で頻繁に使用されるメソッド

post.tags :該当投稿の全てのタグを取得。
post.tags << tag :新しい関係を作成する。
post.tags << [tag1, tag2] :新しい関係を作成する。
post.tag_ids :該当投稿のタグのIDを全て取得する。
post.tags.destroy(tag) :該当投稿からtagを消去する。
post.taggings :該当投稿の全てのtaggingsを取得。
post.taggings.build(tag_id: tag.id) :投稿とtagの関係を作成する。(DBに保存しない)
post.taggings.create(tag_id: tag.id) :投稿とtagの関係を作成する。(DBに保存する)
post.tags.build({}) :該当投稿と結合モデル(tagging)で結びつくタグを作成する。(DBに保存しない)
post.tags.create({}) :該当投稿と結合モデル(tagging)で結びつくタグを作成する。(DBに保存する)
tag.posts.build({}) :該当タグと結合モデル(tagging)で結びつく投稿を作成する。(DBに保存しない)
tag.posts.create({}) :該当タグと結合モデル(tagging)で結びつく投稿を作成する。(DBに保存する)

Many-to-Many(has_and_belongs_to_many)

Many-to-Manyは他のモデルとの間に「多対多」の関係がある事を示す。
モデルAとモデルB共に相互の複数のインスタンスを所有している。
has_and_belongs_to_manyの方式では1つのJOINテーブルを介してモデルAとモデルBが互いのインスタンスを多数所有し合う 。
例えば、複数の投稿(post)が複数のタグ(tag)を持つ場合。

各テーブルのカラム

# CreateUsers(モデルA)
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.timestamps
    end
  end
end

# CreateRoles(モデルB)
class CreateRoles < ActiveRecord::Migration[5.1]
  def change
    create_table :roles do |t|
      t.string :name
      t.timestamps
    end
  end
end

# CreateRolesUsers
class CreateRolesUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :roles_users, id: false do |t|
      t.references :user, foreign_key: true
      t.references :role, foreign_key: true
    end
  end
end

各モデル

# app/models/user.rb
class User < ApplicationRecord
  has_and_belongs_to_many :roles
end


# app/models/tag.rb
class Role < ApplicationRecord
  has_and_belongs_to_many :users
end

Many-to-Many(has_and_belongs_to_many)で頻繁に使用されるメソッド

Many-to-Many(has_many_through)で頻繁に使用されるメソッドを参照。

Polymorphic

PolymorphicであるモデルAが他の複数のモデル(B,C,D)に属していることを、1つの関連付けだけで表現することが可能。
例えば、コメント(picture)が投稿(post)がとユーザー(user)に所属している場合。

各テーブルのカラム

# CreateUsers(モデルA)
class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.timestamps
    end
  end
end

# CreatePosts(モデルB)
class CreatePosts < ActiveRecord::Migration[5.1]
  def change
    create_table :posts do |t|
      t.string :title
      t.references :user
      t.timestamps
    end
  end
end

# Createpictures(モデルC)
class Createpictures < ActiveRecord::Migration[5.1]
  def change
    create_table :pictures do |t|
      t.string :body
      t.integer :imageable_id
      t.string :imageable_type
      t.timestamps
    end
  add_index :pictures, [:imageable_type, :imageable_id]
  end
end

# 以下のようにreferencesを使用してより簡潔に書くことも可能。
# Createpictures(モデルC)
class Createpictures < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.text :body
      t.references :imageable, polymorphic: true, index: true
      t.timestamps
    end
  end
end

各モデル

# app/models/user.rb
class User < ApplicationRecord
  has_many :posts
   has_many :pictures, as: :imageable
end

# app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user
  has_many :pictures, as: :imageable
end

# app/models/picture.rb
class picture < ApplicationRecord
  belongs_to :imageable, polymorphic: true
end

Polymorphicで頻繁に使用されるメソッド

post.pictures :該当投稿の全てコメントを取得。
user.pictures :該当ユーザーの全てコメントを取得。
post.pictures.build :該当投稿に結びつくコメントを作成。(DBに保存しない)
post.pictures.create :該当投稿に結びつくコメントを作成。(DBに保存する)
user.pictures.build :該当ユーザーに結びつくコメントを作成。(DBに保存しない)
user.pictures.create :該当ユーザーに結びつくコメントを作成。(DBに保存する)
post.pictures << picture.new({}) :該当ポストにコメントを関連づけ。
user.pictures << picture.new({}) :該当ユーザーにコメントを関連づけ。

以下のようなImageができるイメージ。

[
  {id: 1, name: "ss", imageable_id: 1, imageable_type: "Post"},
  {id: 2, name: "ss", imageable_id: 1, imageable_type: "User"}
  ]

References

62
47
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
62
47