【Rails】has_many、belongs_to

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

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/4bdbd564-1107-f94f-ff9d-af123e9f70ee.png)
上記のような関係があったとき`Petテーブル`に「犬」と「猫」があってその飼い主が``Ownerテーブル`「佐藤さん」だったときに、
佐藤さんが犬と猫を手放した場合、佐藤さんが飼っているペットを全て削除するということができます。

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

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597913/3d166f14-0944-41e5-7395-1c9466460b74.png)

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

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

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

##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
```
こうすることで`オーナー`は`城`を所有しているという関係になります。

##関連名を変更できる

```rb
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」を追加しマイグレーション実行。

```rb
#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が追加されます。

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

```
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
```
こちらは`「１」対「多」`になります。
owner_idが「２」で伏見城が追加されています。

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

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