0
0

More than 1 year has passed since last update.

【Rails】ancestryを使用し、データをセレクトボックスで表示する方法

Posted at

はじめに

前回、ancestryを用いて親-子のレコードを作成しました。

データ登録時にセレクトボックスで、地方(親)ごとに都道府県(子)を表示、選択できるようにしました。

出来上がりイメージ↓↓
スクリーンショット 2021-09-29 22.31.33.png
スクリーンショット 2021-09-29 22.28.44.png

前提

前回の記事(seed作成まで)は完了していることとします。

今回はpostsテーブル/camp_sitesテーブルに、region_idというカラムを作成し、
投稿記事、キャンプサイトに地域を紐付けて保存できるようにします。

カラムの追加は完了していることとします。

やったこと

posts_controller.rb
  def new
    @regions = Region.where.not(ancestry: nil) #ここを追加
    @post = Post.new
  end

親(地方)のレコードはancestryカラムはnilとなっているので、
Region.where.not(ancestry: nil) で親ではないレコード、つまり子のレコード(都道府県)を取得しています。

app/views/posts/new.html.erb
<%= f.select :camp_site_id, grouped_options_for_select(@regions.map { |p| [ p.name, p.camp_sites.map { |c| [c.site_name, c.id]} ]}), prompt: "選択してください" %>

formに上記を追加します。

f.select :camp_site_id

はformの書き方通りです。

まず、@regionsには子である都道府県のレコードが格納されています(posts_controller.rbを確認)

grouped_options_for_selectは、親をひとまとまりのgroupとして扱ってくれます。

実際にコンパイルされるとこんな感じ↓↓

スクリーンショット 2021-09-29 22.50.50.png

親(地方)が、optgroup
子(キャンプサイト)が、option

で括られているのがわかると思います。

このようにグループでまとめてくれるのが、このメソッドです(便利)。

@regions.map { |p| [ p.name, p.camp_sites.map { |c| [c.site_name, c.id]} ]}

本題のこの記述では、

@regions.map

mapメソッドで@regionsに格納されている配列データの数だけ、ブロック内で処理を行い、
最終的に配列を返してくれます。

mapメソッドの後ろについては、

|p| #ここに@regionsのレコードの一つが入ります(.eachと同様の考え方)
p.name #レコードのnameカラムが表示されます
p.camp_site.map #@regionsのレコードの一つに紐づくcamp_sites(キャンプサイト一覧)を配列データの数だけ処理を行います
|c| #camp_sitesのレコードの一つが入ります
c.site_name, c.id #camp_sitesのレコードの一つの名前を表示します。idも一緒に渡してあげます。

この処理をまとめると、まず、子である都道府県名が表示され、その後camp_site.mapの処理により、1つ1つの都道府県に関連するキャンプサイトが表示されます。

そのため、

関東地方
  東京都
  茨城県
中部地方
  静岡県
  愛知県

上記のように、子(都道府県)→関連するキャンプサイト→子(都道府県)...
と表示ができます。

考え方は同じなため、camp_sites/newについてはコードのみ記載します。

camp_sites_controller.rb
  def new
    @camp_site = CampSite.new
    @regions = Region.where(ancestry: nil) #先ほどと違って、今回は親(地方)をregionsに入れます
  end
app/views/camp_sites/new.html.erb
<%= f.select :region_id, grouped_options_for_select(@regions.map { |p| [ p.name, p.children.map { |c| [c.name, c.id]} ]}), prompt: "選択してください" %>
#親(地方)と親のchildren、つまり子(都道府県)をセレクトボックスに交互に表示します。

終わりに

ancestryを用いてのデータ操作に想像以上に苦戦しました。
一通り解決し、復習することで、だいぶ理解することができました。

0
0
1

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