0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

アソシエーション定義方法について調べてみた

Posted at

はじめに

現在アプリ制作を行っています。作成したER図を元にメンバーの方がmodelを作成してくださったのですが、コードレビューする際に知らないオプションがありなにこれ?となったため、いい機会だと思いどんなオプションがあるのかを調べてみました。

アソシエーションとは?

アソシエーションとはモデル間の関連付けのことで、簡単に言うと2つ以上のテーブルの関係性を定義することです。

関係性を定義することで、複数のテーブルにまたがるデータを簡単に取り出せるようになります。

前提

  • 今回の記事では、以下3つのテーブルがあるときの関係性を例に考えてみます。
Users Communities Documents
id id id
name name title
email body
owner_id
writer_id

テーブル同士の関係性

1. UsersとCommunitiesの関係 (多対多)

  • 1人のユーザーは複数のコミュニティに属す。
  • コミュニティには複数のユーザーが含まれる。

2. UserとDocumentsの関係  (1:多)

  • 1人のユーザーは複数のドキュメントを持つ。
  • ドキュメントは1人のユーザーが書いたものである。

3. CommunitiesとDocuments

  • 割愛

以上のように3つのテーブル間には1対多もしくは多対多の関係が成り立つことが分かり、この関係を踏まえた上で作成したER図が下記になります。

スクリーンショット 2021-04-20 16.43.38.png (40.6 kB)
  • UsersテーブルとCommunitiesテーブルは多対多となるため中間テーブルを用意します。
  • Documentsは書いた人(writer)と所有する人(Owner)を分けるためにidを分けてます。

以上の前提条件を踏まえた上でこれからアソシエーションを定義していきましょう。

アソシエーションの定義方法

まず、基本的なアソシエーションの定義方法は以下になります。

  • belongs_to
  • 関連するテーブルに属することを表す
  • 1つのデータを割り当てる(下記の例なら一人のユーザと一つのコミュニティを紐付ける)
community_user.rb
class CommunityUser < ApplicationRecord
  belongs_to :user
  belongs_to :community
end
  • has_many
    • 複数データを参照する
    • 1対多の関係を表す
user.rb
class User < ApplicationRecord
	has_many :documents
end

ユーザーは複数ドキュメントのデータを参照できる

  • has_many :through
    • 多対多の関係を表す
    • throughで定義した中間テーブルを通して直接、相手側のテーブルにアクセスできる
user.rb
class User < ApplicationRecord
	has_many :communities, through: :community_users
end

以上はよく使うアソシエーション定義方法だと思いますが、次からはアソシエーションに用意されているオプションを紹介していきます。

アソシエーションのオプション

class_nameオプション

一つのモデルに対して違う名前で値を取り出したい時に使う。

user.rb
class User < ApplicationRecord
    has_many :documents,
    has_many :have_documents, class_name: "Document", as: :owner
end

以上のようにすることで、documentsではすべてのドキュメントを取り出し、have_documentsではDocumentsテーブルのowner_idを持ったドキュメントのみを取り出せるようになります。

dependentオプション

あるモデルを削除した際の関連するモデルに対する挙動を定義する。

  • dependent: :destroy
    • 関連付けしているモデルも一緒に削除する
    • ActiveRecordを介して関連付けの数だけDELETEが実行される
user.rb
class User < ApplicationRecord
	has_many :community_users, dependent: :destroy
end

以上のようにすることでUserが削除された際に、紐づくCummunity_userも一緒に削除される。

  • dependent: :delete_all

    • 直接SQLを発行してDELETEを1回だけ実行する
  • dependent: :nullify

    • 関連付けしているモデルは削除しない
user.rb
class User < ApplicationRecord
	has_many :documents, dependent: :nullify
end

これでユーザーが削除されてもユーザーの作成したドキュメントは一緒には削除されません。

foreign_key

  • 参照先テーブルの外部キーのカラム名を明示

inverse_of

  • どちらのモデルからでもインスタンスを参照できるようにする
user.rb
class User < ApplicationRecord
	has_many :documents, foreign_key: :writer_id, inverse_of: "writer"
end

以上のようにすることで自分の書いたドキュメントで有ることがわかりやすくなる。

参考記事

おわりに

まだ理解が怪しい所もあるため、間違いなどご指摘や、他にもこんなオプションあるよなど教えて頂けると嬉しいです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?