0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

1:nアソシエーションから生成した「選択肢がグループ化されたセレクトボックス」に、テーブルのデータでない値からなる選択肢を追加しようとしたら、pluckメソッドが便利だった

Posted at

前提

アソシエーション

  • League モデルと Team モデルには 1:n のアソシエーションがあるとします。
league.rb
# リーグモデル
class League < ApplicationRecord
  has_many :teams
end
team.rb
# チーム(大学)モデル
class Team < ApplicationRecord
  belongs_to :league
end

やりたいこと

  • 以下のHTMLを生成させたいです。
<!-- チーム名を入力するためのセレクトボックス -->
<select name="event[top_team]" id="event_top_team">
  <option value="">選択してください</option>
  <optgroup label="1部リーグ">
    <option value="aa大学">aa大学</option>
    <option value="bb大学">bb大学</option>
    <option value="cc大学">cc大学</option>
    <option value="dd大学">dd大学</option>
  </optgroup>
  <optgroup label="2部リーグ">
    <option value="ee大学">ee大学</option>
    <option value="ff大学">ff大学</option>
    <option value="gg大学">gg大学</option>
    <option value="hh大学">hh大学</option>
  </optgroup>
  <optgroup label="3部リーグ">
    <option value="ii大学">ii大学</option>
    <option value="jj大学">jj大学</option>
    <option value="kk大学">kk大学</option>
    <option value="ll大学">ll大学</option>
  </optgroup>
  <optgroup label="入替戦">
    <option value="1部4位大学">1部4位大学</option>
    <option value="2部1位大学">2部1位大学</option>
    <option value="2部4位大学">2部4位大学</option>
    <option value="3部1位大学">3部1位大学</option>
  </optgroup>
</select>

問題点

  • アソシエーションを使って選択肢がグループ化されたセレクトボックスを生成する grouped_collection_select メソッドというものがあり、それを使えば記述量少なく書けそうですが、「入替戦」グループの値はテーブルのデータではないため、その部分が実装できません。
_form.html.erb
<%= f.grouped_collection_select(:top_team, League.all, :teams, :name, :name, :name, {include_blank: '選択してください'} %>
<!-- これでは「入替戦」グループの値を出力できない -->

最初に到達した解決策

  • ビュー側の select メソッドに配列(下の例でいう select_box )を渡すことで解決しようとしました。
  • そのアプローチはとりあえず良いと思ったのですが、その配列を生成する方法が少し冗長に思えました。
  • select メソッド(DBからデータを取得する際に、指定カラムのデータのみ取得するもの)や、 collection_singular_ids メソッドの存在は知っていたため、冗長に見えたのかと思います(なんかもうちょっといい書き方ありそう、みたいな軽い感じですが。。。)
event.rb
  def self.make_team_select_box
    leagues = League.all.order(name: :asc)
    select_box = []

    leagues.each do |league|
      league_teams = []
      league_teams << league.name

      # ここから
      teams = league.teams
      team_names = []
      teams.each do |team|
        team_names << team.name
      end
      # ここまでが冗長?
      # -> 要するに、「チーム名の配列をもっと手軽に生成したい」ということになる

      league_teams << team_names
      select_box << league_teams
    end

    select_box << ['入替戦', ['1部4位大学', '2部1位大学', '2部4位大学', '3部1位大学']]
  end
_form.html.erb
<%= f.select :team, Event.make_team_select_box, {include_blank: '選択してください'} %>

最終的に到達した解決策

  • ビュー側は上記のままです。
  • 先ほど冗長に思えた配列生成の部分で、より良い書き方を調べていると、 pluck メソッドがはまりました。
  • pluck メソッドは、データ取得結果から指定したカラムのデータのみを配列にして返します。
event.rb
  def self.make_team_select_box
    leagues = League.all.order(name: :asc)
    select_box = []

    leagues.each do |league|
      league_teams = []
      league_teams << league.name
      league_teams << league.teams.pluck(:name)
      select_box << league_teams
    end

    select_box << ['入替戦', ['1部4位大学', '2部1位大学', '2部4位大学', '3部1位大学']]
  end

参考

0
0
0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?