📝

Ruby on Railsでチェックボックス(複数選択)を作る

2023/06/12に公開

今日は複数選択可能なチェックボックスをどうやって作るか、どうデータベースに保存するのかについてまとめます。

チェックボックスとは?

チェックボックスはユーザーがクリックすることで項目のオン/オフが出来るボックスです。
「利用規約に同意する はい/いいえ」のようなユーザーの意思を確認するような用途や、アンケートフォームのように、複数の選択肢から任意の0個以上の選択をさせる場合などに使われます。
今回は、複数選択させたい場合の実装方法について書き記します。

チェックボックスの実装の下準備

複数選択させたい実装方法の場合は、選択肢を保存するテーブルと中間テーブルの作成が必要となります。
以前作成したプロフィールを登録するアプリに趣味(hobby)を複数登録できるよう追加で実装していきます。

テーブル構成

profilesテーブル

Column Type Options
name string null: false
sex string null: false
  • has_and_belongs_to_many :hobbies

hobbiesテーブル

Column Type Options
category string
  • has_and_belongs_to_many :profiles

hobbies_profilesテーブル (中間テーブル)

Column Type Options
profile_id references null: false, foreign_key: true
hobby_id references null: false, foreign_key: true

今回は中間テーブル用のモデルを作らず、has_and_belongs_to_manyを使用してアソシエーションを組んでいます。詳しくは下記リンク参照↓

https://railsguides.jp/association_basics.html#has-and-belongs-to-many関連付け

hobbiesテーブル(選択肢用のテーブル)にレコードを保存

選択肢を作成します。こんな感じ。

チェックボックスの実装

チェックボックスをビューで作成するには、フォームヘルパーのcollection_check_boxesを使用します。

<%= form.collection_check_boxes :hobby_ids, Hobby.all, :id, :category %>

collection_check_boxesの1つめのパラメーターを:hobby_idsとしました。これはProfileを保存する際に、中間テーブルのhobby_idにも情報を保存するためです。
2つめのパラメータHobby.allはhobbiesテーブルに保存されている全レコードを意味します。
詳しくはこちら↓

https://railsguides.jp/form_helpers.html



ビューの表示とHTML出力は以下のようになります。

<input type="hidden" name="profile[hobby_ids][]" value="">

<input type="checkbox" value="1" name="profile[hobby_ids][]" id="profile_hobby_ids_1">
<label for="profile_hobby_ids_1">スポーツ</label>

<input type="checkbox" value="2" name="profile[hobby_ids][]" id="profile_hobby_ids_2">
<label for="profile_hobby_ids_2">読書</label>

~ 以下 {id: 9, category: "その他"} まで同様に作成 ~



それでは、趣味の項目2つ(1.スポーツ、3.映画)を選んでProfileを保存してみます。
このとき、paramsは下記のようになります。

 {"authenticity_token"=>"wr9ZnNuKV5XZ9rten3ODhSA8r/rmqcMI0D/eB5J6o+m73NoOAmQXY9+P5IloYk3Lb4juPrcEZkJ5eRr3uTaIew==", 
 "profile"=>{"name"=>"さとし", "sex"=>"male", "hobby_ids"=>["", "1", "3"]}, "commit"=>"SEND", "controller"=>"profiles", "action"=>"create"}

ハッシュのキーhobby_idsの値が配列["", "1", "3"]になっていますので、ストロングパラメーターで配列を受け取れるようにしてあげます。

def create
  @profile = Profile.new(profile_params)
  @profile.save
  redirect_to root_path
end

private
def profile_params
  params.require(:profile).permit(:name, :sex, hobby_ids:[])
end

レコード保存の記述はいつも通りの感じでOK。アソシエーションを組んでいるおかげで、Profileの保存と同時に中間テーブルにもレコードが保存されます。

選択肢用テーブルをActiveHashで代用できないか?

中間テーブルつくるのめんどくさいので選択肢用のテーブルは変更があまりないので、ActiveHashで代用できないかなと色々試行錯誤してみましたが、どうやらActiveHashは多対多のアソシエーションは組むことができないようです。
メソッドを追記したりすればいけるみたいなのですが、使いこなせる自信があまりなかったので正攻法(中間テーブル作成)をご紹介しました。

ActiveHashの使い方や、ActiveHashで多対多を実現するための記述は下記リンクがわかりやすくておすすめです。

https://hataworakuni.net/active-hash

Discussion