11
10

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.

【Rails】has_many、belongs_to

Last updated at Posted at 2020-03-10

#has_many
テーブル同士を関連づけるためのものです。
関連づけているのでテーブルの操作等が効率的にできます。

##関連付け
関連付けとはテーブル等で関係があるものについて明示的に表現することです。

image.png
上記のような関係があったときPetテーブルに「犬」と「猫」があってその飼い主が``Ownerテーブル`「佐藤さん」だったときに、
佐藤さんが犬と猫を手放した場合、佐藤さんが飼っているペットを全て削除するということができます。

こちらは関係が「1」対「多」になります。

image.png

このようなテーブルの関係の場合、Petテーブルkeeper_id(飼い主)seller(販売員)が加わっておりPetテーブルに2つの以上の関連付けがされています。

こうするとPetを登録したときに飼い主と販売員の2人を関連づけることができます。
関連づけることでテーブルを追加したり削除するときにまとめることができます。

上の関係は「多」対「多」になります。

##has_manyの基本的な実装方法

rails g model owner name:string
rails g model castle castle:string owner_id:integer

「所有者」と「城」のモデルを作成します。
rails db:migrateで作成されたマイグレーションファイルを実行します。

Castle.create(castle:"大阪城",owner_id:2)
Castle.create(castle:"岐阜城",owner_id:3)
Castle.create(castle:"安土城",owner_id:3)
Castle.create(castle:"江戸城",owner_id:1)
Castle.create(castle:"首里城",owner_id:4)
Owner.create(name:"徳川家康")
Owner.create(name:"豊臣秀吉")
Owner.create(name:"織田信長")

CastleテーブルOwnerテーブルに上記のカラムを追加します。

app/models/owner.rb
has_many :castles, dependent: :destroy

このようにユーザモデルに記載しOwnerがCastlesを所有していることにします。
dependent: :destroyと記載することでオーナーが所有する城を全て削除することを簡潔に命令できるようになる。

#belongs_to

app/models/castle.rb
belongs_to :owner

こうすることでオーナーを所有しているという関係になります。

##関連名を変更できる

belongs_to :holder ,class_name: 'Owner',foreign_key: 'owner_id'

このような記載方法にすることでbelongs_to :〇〇〇の〇〇〇部分が変更可能になります。
ただし追記でclass_nameは指定のテーブルを、foreign_keyにはモデル+_idを記載しなければいけません。

これでholderという名前でOwnerテーブルにアクセスすることができるようになります。

##referencesを使用してidを関連づける方法

rails g model castle castle:string owner_id:integer
↓
rails g model castle castle:string owner:references

このようにモデルを作成する際に関連づけられたidを設定していましたが、記載の方法は上記のように変更することができます。

owner:references

これでowner_idがinteger型で作成されます。
またapp/model/castle.rbにはbelongs_to :ownerが自動的に追加されます。

##throughを用いてより複雑な関連付けを行う
has_many :throughを使用すると「多」対「多」を表現することが可能です。

rails g model keeper name:string
rails g model seller name:string
rails g model pet name:string keeper:references seller:references
rake db:migrate

モデル「keeper」、「seller」、「pet」を追加しマイグレーション実行。

#app/models/keeper.rb
has_many :pets
   has_many :sellers, through: :pets

#app/models/seller.rb
has_many :pets
  has_many :keepers, through: :pets

モデルごとのファイルに上記を記載することで「多」対「多」の関係が成り立ちます。
また、 petモデルを作成するときにrefalenceを使用していることにより、自動的にbelongs_toが追加されます。

##「1」対「多」、「多」対「多」でのデータ追加

owner = Owner.find(2) #豊臣秀吉を取得
owner.castles.create(castle:"伏見城”)
Hirb.enable #表形式で出力
Castle.all

#【実行結果】
+----+--------+----------+---------------------------+---------------------------+
| id | castle | owner_id | created_at                | updated_at                |
+----+--------+----------+---------------------------+---------------------------+
| 1  | 大阪城 | 2        | 2017-07-05 17:41:28 +0900 | 2017-07-05 17:41:28 +0900 |
| 2  | 安土城 | 3        | 2017-07-05 17:41:28 +0900 | 2017-07-05 17:41:28 +0900 |
| 3  | 江戸城 | 1        | 2017-07-05 17:41:28 +0900 | 2017-07-05 17:41:28 +0900 |
| 4  | 伏見城 | 2        | 2017-07-06 10:13:22 +0900 | 2017-07-06 10:13:22 +0900 |
+----+--------+----------+---------------------------+---------------------------+
4 rows in set

こちらは「1」対「多」になります。
owner_idが「2」で伏見城が追加されています。

keeper = Keeper.create(name:"田中太郎") #新しい飼い主
seller = Seller.create(name:"立川絢香" ) #販売した人
keeper.pets.create(name:"ウーパールーパー",seller: seller) #ウーパールーパーを購入
Hirb.enable #表形式で出力
Pet.all

【実行結果】
+----+------------------+-----------+-----------+---------------------------+---------------------------+
| id | name             | keeper_id | seller_id | created_at                | updated_at                |
+----+------------------+-----------+-----------+---------------------------+---------------------------+
| 1  | プラナリア       | 1         | 3         | 2017-07-06 10:47:40 +0900 | 2017-07-06 10:47:40 +0900 |
| 2  | 文鳥             | 3         | 2         | 2017-07-06 10:47:40 +0900 | 2017-07-06 10:47:40 +0900 |
| 3  | カブトムシ       | 3         | 1         | 2017-07-06 10:47:40 +0900 | 2017-07-06 10:47:40 +0900 |
| 4  | 猫               | 2         | 2         | 2017-07-06 10:47:40 +0900 | 2017-07-06 10:47:40 +0900 |
| 5  | 犬               | 2         | 1         | 2017-07-06 10:47:40 +0900 | 2017-07-06 10:47:40 +0900 |
| 6  | クモ             | 1         | 2         | 2017-07-06 10:47:41 +0900 | 2017-07-06 10:47:41 +0900 |
| 7  | ウーパールーパー | 4         | 4         | 2017-07-06 10:53:40 +0900 | 2017-07-06 10:53:40 +0900 |
+----+------------------+-----------+-----------+---------------------------+---------------------------+
7 rows in set

こちらが「多」対「多」になります。

11
10
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
11
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?