Ruby on Rails アソシエーションの応用 class_name 【一つのモデルを複数に分岐する】

忘れているかもしれないので、
まずは基本から復習していきましょう！！


## 基本（1対多）

userが複数の商品（products）を保持している関係だとしたら、

```ruby:user.rb
class User < ApplicationRecord
  has_many :products
end
```
productsはuserに保持されているので、

```ruby:product.rb
class Product < ApplicationRecord
  belongs_to :user
end
```

userというフォルダに、複数のproductファイルがある感覚と同じ。
![スクリーンショット 2020-02-20 0.21.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455403/2427aec9-4e5c-9420-3e41-524409db9516.png)

だからuserは単数形、productは複数形
productは親フォルダのuserに入っているから、belongs_to :user
userフォルダはたくさんのproductを持っているから、 has_many :products




## 応用（1対多）： class_name

じゃあ、productsを保持するuserが、販売者（seller）・購入者(buyer)に分ける場合はどうしましょうか？
seller・buyerにそれぞれモデルは必要ありません。userモデルを分けてあげれば大丈夫です。じゃないとIDが変わって逆に大変ですから。

userはproductsを複数保有しているので同じです。
（次にやります。）

```ruby:user.rb
class User < ApplicationRecord
  has_many :products
end
```

productsに紐づくuserを"seller"と"buyer"に分けたいので、下記ようにします。

```ruby:product.rb
class Product < ApplicationRecord
  belongs_to :seller, class_name: "User", foreign_key: "seller_id"
  belongs_to :buyer, class_name: "User", foreign_key: "buyer_id"
end
```

「なんじゃこりゃ！！」、となったと思います。要点を抑えたら簡単です。
では解説していきます。

### STEP1 モデル名は変えられる。

基礎だと下記のように、ProductはUserに紐づいていました。

```ruby:product.rb
class Product < ApplicationRecord
  belongs_to :user
end
```

belongs_to :userと記述されていますが、この"user"という名前を変えられます。
「userじゃなくて、ownerに変えたいなあ？？」
このように名前を変えたい場合にclass_nameを使います。

```ruby:product.rb
class Product < ApplicationRecord
  belongs_to :owner, class_name: "user" # belongs_to :userと同じです。
  #  元はUserモデルだけど（class_name: "user"）、ownerって表示に変えますわ（belongs_to :owner）
end
```

### STEP2: Userモデルを分ける

１つだとSTEP1だけで変えられます（まあ、変える必要ないんだけど）。
では、userをsellerとbuyerと２つに分けたい場合、どうすればいいのでしょうか？



まずはproductsテーブルをみてください。
![スクリーンショット 2020-02-20 0.33.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455403/0bab6222-ed99-1884-b2de-617b8225730a.png)
productレコードのカラムに"buyer_id（user_id）"と"seller_id(user_id)"があります
このカラムに入れるidを元にuserをsellerとbuyerに分けています。

```ruby:product.rb
class Product < ApplicationRecord
  belongs_to :seller, class_name: "user", foreign_key: "seller_id"
  # belongs_to :seller, class_name: "user" = （Productに紐づく） Userモデルをsellerと定義するわ。　
  # foreign_key: "seller_id" = user_idはProductレコードの『seller_idカラム』のid番号を使うわ

  belongs_to :buyer, class_name: "user", foreign_key: "buyer_id"
  # belongs_to :buyer, class_name: "user" = （Productに紐づく） Userモデルをbuyerと定義するわ。　
  # foreign_key: "seller_id" = user_idはProductレコードの『buyer_idカラム』のid番号を使うわ
end
```
これで二つに分けられました。
カラムに紐づくid番号で分けたあげた分けです。

### STEP3: Productを複数に分ける

販売中、売却済み、購入した商品に分けます。

販売中だけ習得する
![スクリーンショット 2020-02-20 1.47.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455403/8317bb2d-6045-2793-432e-73674e18ec80.png)

売却済みだけ取得する
![スクリーンショット 2020-02-20 1.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455403/a7d05910-c7f5-edd7-91ad-db285c5a205d.png)

購入した商品だけ取得する
![スクリーンショット 2020-02-20 1.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455403/4914c0cb-029f-0a98-0bb8-0d7beba72280.png)



```ruby:user.rb
class User < ApplicationRecord
  # 全部取得
  has_many :products

  # 販売中
  has_many :selling_products, class_name: "product", foreign_key: "seller_id", -> { where("buyer_id is NULL") }
  # Productモデル名を selling_productsに定義するわ = has_many :selling_products, class_name: "product"
  # productレコードの”seller_id”カラムに自分のidが入っている、productだけ取得するね = foreign_key: "seller_id" （ userはhas_many: productsだから ）
  # でも、buyer_idが入っていないproductだけにする = -> { where("buyer_id is NULL") }

  # 買った商品
  has_many :bought_products, class_name: "product", foreign_key: "buyer_id"
  # Productモデル名を bought_productsに定義するわ = has_many :bought_products, class_name: "product"
  # productレコードの”buyer_id”カラムに自分のidが入っている、productだけ取得するね = foreign_key: "buyer_id" （ userはhas_many: productsだから ）
  
  # 売却済み商品
  has_many :sold_products, class_name: "product", foreign_key: "seller_id", -> { where("buyer_id is not NULL") }
  # Productモデル名を sold_productsに定義するわ = has_many :selling_products, class_name: "product"
  # productレコードの”seller_id”カラムに自分のidが入っている、productだけ取得するね = foreign_key: "seller_id" （ userはhas_many: productsだから ）
  # でも、buyer_idが入ってるproductだけにする = -> { where("buyer_id is not NULL") }
end
```


### まとめ

class_nameでモデルを分ける際は、

```ruby:まとめ
has_many :〜側のモデルのカラムを使って分ける。

# 今回だと
   has_many :products 
   # productにuser_idを紐づけるので、これを使って分ける。
   # 親元のuserのカラムにproduct_idは入れないので、userのカラムを使って分けることはできない。
   
まとめ：　１対多なら、 『多』のカラムを使って分けよう ( foreign_key: )
```

## エラーポイント

```:エラー
uninitialized constant
```

が表示された場合、class_nameが小文字になっています。

```ruby:エラー
class_name: "product" = 大文字 = エラーなし
class_name: "product" = 小文字 = エラー：uninitialized constant
```




## 参考リンク
[【初心者向け】丁寧すぎるRails『アソシエーション』チュートリアル【幾ら何でも】【完璧にわかる】](https://qiita.com/kazukimatsumoto/items/14bdff681ec5ddac26d1)

[railsアソシエーションオプションのメモ](https://qiita.com/tomoharutt/items/e548186c763079327ed1)
[アソシエーションにおけるclass_nameの定義！](https://qiita.com/wacker8818/items/eccdf0a63616feb14a70)