後へ      Topへ      次へ

joins: モデルデータの連携

サンプルプログラムでは、
段(Step) → 棚(Cabinet) → 階層(Floor)、の3段階を持っています。

Steps の表示画面で Cabinet を表示する際、
Cabinet 名に加えて、属する Floor も付記すると親切です。
e.g. [1F] C1-100 など。

参考リポジトリ: https://github.com/Bonv-dev/book_mgmt/commit/de7eecb

joins 1段階

Cabinet → Floor の関連性を示すのに使えるのが joins です。
Cabinet.joins(:floor) と書きます。
これで、cabinet と、各cabinet が持っている floor_id の floor 、
両方のカラム値を同時に参照できます。
例えば、
.pluck("cabinets.id, floors.name, cabinets.name")
のようにです。

後は、
.map { |id, fname, cname| [id, "[#{fname}] #{cname}"] }.to_h
で、{id=>”[Floor名] Cabinet名”} の hash にして View に渡します。

joins 2段階以上

Step → Cabinet → Floor の関連性も joins で表現できます。
Step.joins(cabinet: :floor)
と書きます。
こちらも、サンプルプログラムで使用しています。

仮に、  
Step → Cabinet → Floor → Building の関連性なら、  
```Step.left_joins(cabinet: { floor: :building })```  
と書けると思います。(未検証)  

中級

Cabinet.joins(:floor) が使えるのは、
Cabinet が floor_id を持っていて、モデルで

class Cabinet < ApplicationRecord
  belongs_to :floor

と書いている故です。
joins は、SQL でいうと INNER JOIN で、

SELECT cabinets.*
FROM cabinets
INNER JOIN floors
  ON floors.id = cabinets.floor_id;

と書くのと同等です。
(cabinets.* 部分は、後続のコードによって変わります)
floors.id と cabinets.floor_id が一致するレコードのみを抽出します。

INNER JOIN は、
JOIN する側 (floors) に ON に該当するレコードがない場合、
JOIN される側 (cabinets) も抽出されません。
これは、cabinets のレコード側が欠落する可能性があることを示しています。

欠落すると困る場合は、
Cabinet.left_joins(:floor)
を使います。
条件に合致しない floor のカラムには nil が入ります。

left_joins は SQL でいう LEFT OUTER JOIN です。


後へ      Topへ      次へ