ruby on railsにてmodel間の関連(one2manyとか)を定義する方法を調べたときに少してこづったので、どうやったのかを記しておこうと思います。
やりたかったこと
下記の2つようなテーブルを作成したいです
Userテーブル
PK | FK | カラム名 | 項目名 |
---|---|---|---|
◯ | id. | ユーザ番号 | |
メールアドレス | |||
password_digest | パスワード | ||
display_name | 表示名 |
Task テーブル
PK | FK | カラム名 | 項目名 |
---|---|---|---|
◯ | id. | タスク番号 | |
name | タスク名 | ||
◯ | user_id | 作成ユーザー | |
◯ | asignee_id | 担当者 |
Taskテーブルのusr_idとasignee_idがUserテーブルのidとなるようにしたかったです。
UserとTaskがone2manyの関係ですね。
関連付けの方法を調べてみた
関連付けをする方法はすぐわかったのですが、カラム名を明確に指定するやり方が見つからなくて少し困りました。
User model
class User < ApplicationRecord
has_many :tasks, foreign_key: "user_id", primary_key: "id"
has_many :tasks, foreign_key: "assignee_id", primary_key: "id"
冗長なコードになっている気はしますが、
- 第一引数(:tasks)
- 関係があるオブジェクトの指定
- 複数形にする必要がある
- 第二引数(foreign_key: "user_id")
- 参照先のテーブルのカラム名
- ここではTaskテーブルのuser_idカラムと、assignee_idをそれぞれ指定しています
- 第三引数(primary_key: "id")
- 参照元のテーブルのカラム名
- ここではUserテーブルのidカラムを指定しています
Task model
class Task < ApplicationRecord
belongs_to :user, foreign_key: "user_id"
belongs_to :user, foreign_key: "assignee_id"
- 第一引数(:user)
- 関係があるオブジェクトの指定
- こっちは単数系
- 第二引数(foreign_key: "user_id")
- 参照元のカラム名の指定
rspecによるテスト
関連付けがきちんと行われているかをテストするのにはsholuda-matchersが便利でした。
Taskのspecでは下記のように記述をするだけでテストができます。
it "belong to user id " do
belong_to(:user_id).class_name(User)
end
it "belong to assignee id" do
belong_to(:assignee_id).class_name(User)
end
belong_to
では、どのカラムの関係をテストするかを指定して
class_name
では、どのmodelを参照しているのかを指定してあります。
まとめ
公式のドキュメントを読んだらすぐに分かったので、記事にするほどでもないかもしれませんが備忘録的に残しておきます。
ruby on railsはこっちが明示的に記述しなくても裏でよしなにやってくれていることが多すぎて何やってるかよく分かんないことが多い印象です。
ちゃんとドキュメント読みます...