Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
51
Help us understand the problem. What is going on with this article?
@_akira19

[Rails] form_with内でのcollection_selectの使い方(ドロップボックスでの検索)

More than 1 year has passed since last update.

簡単にできるかなと思って少しだけハマったのでform_with内でのcollection_selectの使い方を整理します。

実現したい事

  1. ドロップボックスで選択した項目による検索
  2. ドロップボックスの中身はDBから取得

環境

Ruby version 2.5.1
Rails version 5.1.6

サンプル

Userが所属している会社の住所の都道府県で検索したい。
リレーションは下記の様になります。
User(tournament): belongs_to :company
Company(field): has_many :users

また、companyテーブルはprefectureというカラムを持っているとします。

index.html.slim
= form_with(url: search_users_path, method: :get, local: true) do |form|
  = form.label :"都道府県"
  = form.collection_select :prefecture, Company.group(:prefecture).order(id: :desc), :prefecture, :prefecture, {prompt: ""}
  = form.submit

各コードの説明します。

form_with: form_forとform_tagを合わせたものです。詳しくは他の記事を参照してください(【Rails 5】(新) form_with と (旧) form_tag, form_for の違い)。ここではsearch_users_pathにフォームの内容を送る様になっています。
local: trueはform_withはデフォルトで非同期通信で送信する様になっているので、これで無効にしています。(もちろん必要あれば有効にしてください。)

collection_selectはDBの情報を元にドロップボックスを生成するメソッドです。
下記にどの様に使われるかまとめます。コメント部分は上記の例で実際に記述した項目を書いています。

sample.rb
collection_select(
  object, #今回はform_withで既にオブジェクトを渡しているので省略(省略しないとエラーになります。)
  method, #:prefecture : paramsで送る時のkeyになります。つまり今回はparams[:prefecture]で選択したドロップボックスの項目が取得できます。
  collection, #Company.group(:prefecture).order(id: :desc) : 実際にドロップボックスに入る配列を渡します。
  value_method, #:prefecture : optionタグにセットされるvalue属性になります。<option value="ここに値が入る(今回はcompanyの都道府県の値)">
  text_method, #:prefecture : optionタグにセットされる実際のテキストになります。つまり今回の場合は<option value="千葉県">千葉県</option>みたいなhtmlが出力されます。
  options = {}, #{prompt: ""} : オプションです。このオプションではドロップボックスの一番上を空欄に指定しています。
  html_options = {} #省略 : htmlオプションです。
) 

collectionのところでCompany.group(:prefecture).order(id: :desc)としていますが、これはgroupメソッドを使ってCompanyモデルのprefectureカラムから重複を除いたものを出力しています。これをしないで例えばCompany.allとしてしまうと東京の会社が3社あったらドロップボックス内に"東京"が3つ出てきてしまいます。なのでgroupを使ってprefectureが同じものは1つだけ抽出しています。

あとはコントローラで選択した都道府県にある会社を抽出します。

users_controller.rb
#他のアクションは省略
def index
  @users = User.all
end

def search
  companies = Company.where(prefecture: params[:prefecture]) #選択した都道府県にある会社を全て取り出している。
  @users = User.where(company_id: companies.pluck(:id)) #抽出した会社からidだけを取り出して、その会社に所属しているuserを抽出している。
  render "index"
end

pluckの使い方は他の記事やサイト様にお任せしますが、companiesからidだけを抜き出して配列で出力してくれます。

まとめ

見返すと大した事はしていないのですが、結構時間かかったのでまとめました。
もっと良い方法があれば教えていただけると助かります。

参考情報

Can someone explain collection_select to me in clear, simple terms? (Stack Overflow)

51
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
_akira19
Twitter: @_akira19
bajji
2019年創業のスタートアップ 。感情日記SNS『Feelyou(フィールユー)』、ブロックチェーンを活用したSNS『bajji(バッジ)』を開発しています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
51
Help us understand the problem. What is going on with this article?