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

# 前提

## アソシエーション

- `League` モデルと `Team` モデルには `1:n` のアソシエーションがあるとします。

```league.rb
# リーグモデル
class League < ApplicationRecord
  has_many :teams
end
```

```team.rb
# チーム（大学）モデル
class Team < ApplicationRecord
  belongs_to :league
end
```

## やりたいこと

- 以下のHTMLを生成させたいです。

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

# 参考
- [Active Record の関連付け (アソシエーション) - 4.3.1.6 collection_singular_ids](https://railsguides.jp/association_basics.html#has-many%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%82%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89-collection-singular-ids)
- [Ruby on Rails 5 アプリケーションプログラミング](https://www.amazon.co.jp/Ruby-Rails-5%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/4774188832/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=Ruby+on+Rails+5%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1555163469&s=books&sr=1-1)