バートリーのさいとうです。
今回は
【Rails】フォームヘルパーを利用したチェックボックスの複数選択の方法と、謎の空の値の存在を解明
というテーマで、railsの話をします。
railsには、フォームヘルパーというものが存在します。これがめちゃくちゃ便利。
今回は、このフォームヘルパーの中でも
複数選択のチェックボックスの選択内容から値を取得して、パラメータに載せる方法を紹介します。
結論から申し上げると、collection_check_boxesというメソッドを利用します。
しかし、こいつが意外と曲者でして、僕自身もつまづいたその記述方法と注意点を書いていこうと思います。
この記事を読めば
- collection_check_boxesの利用方法が1からわかる
- collection_check_boxesの利用時の注意すべき2つの点がわかる
- チェックボックスの複数選択のパラメーターについて、グッと理解が深まる
と思いますので、一緒にチェックボックスのことを勉強してきましょう。
collection_check_boxesの使い方
では、早速collection_check_boxesの使い方を紹介していきます。
ソースコードはこちらです。まずはメソッドの定義から見ていきます。
def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
end
なんだか引数がたくさんありますね。
一つずつ説明していきます。
collection_check_boxesの引数
(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
・object:
form_forのようにモデルを引数にとるフォームヘルパーを利用していれば、省略可能です。どのモデルに対してなのか、ということを表すことができます。
・method:
実際に保存される値を持つキーになります。パラメータの中ではこのように立ち振る舞います。
{ "method" => {値} }
・collection:
対象となるコレクションを指します。例えば、以下のように取得したレコードの集合などを入れたりします。
@sample_users = User.where.not(email: nil).select(:email)
このようなActiveRecordのインスタンスを埋め込むことができます。(配列とかも入れられるのかな…)
・value_method, text_method:
valueは、実際にパラメーターに含めたい値をシンボルの形で記述します。
textは、文字通り表示したい値をシンボルの形で記述します。例えばこんな感じ
@articles= Article.where.not(tag: nil).select(:tag)
#sample.html.haml
= form_for :article do |f|
= f.collection_check_boxes :tags, :@articles, :id, tag, ...
この場合、@articlesで取得したレコードのtagを実際に表示し、パラメータには選択されたarticlesテーブルのレコードidが含まれるようになります。
options = {}, html_options = {}:
optionsには、railsが提供している様々なオプションを。
html_optionsには、htmlに関するオプションを付与します。
ここに関しては、詳しく後述します。
一旦それぞれの引数の意味合いはこんな感じです。
二つの注意点
collection_check_boxesの使い方について解説したので、実際に利用する際の僕が実際に詰まった注意点を二つ挙げます。
- パラメーターに、謎の空欄が含まれる
- optionsとhtml_options、それぞれ書く順番に気をつける
それぞれの注意点と、その解決方法を見ていきましょう。
パラメータに謎の空欄が含まれる
実際の様子を見てみましょう。
= form_for :article do |f|
= f.collection_check_boxes :tags, :@articles, :id, tag, {}
例えばidが1と2のものを選択してリクエストを送ると、こんなパラメータになります。
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"hoegfuga",
"articles"=>
{
"tags"=>["1", "2", " "],
}
"commit"=>"決定する"
}
6行目、tagsのvalueの配列の最後に、空欄の””が含まれています。
これはなんでしょうか?こちらの回答を参考にすると
チェックされない時に何も送られない、という事態を避けるために、Rails側が自動で空の値のhiddenを追加しています。
ということでした。Railsの心遣いだったということですね。
このままでも扱うこと自体は可能みたいですが、僕は気持ち悪かったので無くそうと思いました。
そこで、上記の記事を参考にし、include_hidden: falseを付与することで、この謎の空欄をパラメータに含めないようにすることができました。
ここで、もう一つの注意点にぶち当たります。
optionsとhtml_optionsの書く順番には気をつける
先ほども出てきましたが、optionsとhtml_optionsに含めることができるオプションは異なります。
ここで、先ほど出てきたinclude_hidden: falseを付与する時に少し注意点があります。
include_hidden: falseは、railsが提供しているオプションであることから、optionsに含める必要があります。
= f.collection_check_boxes :tags, :@articles, :id, tag, {include_hidden: false}, html_options: {}
つまり、以上のように書く必要があります。
html_optionsの方に、もしくは引数のインデックスが該当する方に書いたら反応してくれません。
なので、実際はこのように記述されるでしょうか。
= f.collection_check_boxes :tags, :@articles, :id, tag, {include_hidden: false}, {class: "hpge", onchange: "hogeFuga()"}
これで、collection_check_boxesの使い方と注意点を確認することができました。
まとめ
今回は、フォームヘルパーを利用したチェックボックスの複数選択の方法と、謎の空の値の存在を解明し、その解決策までみてきました。
意外とできそうできない複数選択チェックボックス、パラメータにも要注意ですね。
このブログは、月に15本を目標に、実務から学んだプログラミングのあれこれを発信しています。
誰かのためになれば、嬉しいです。
最後まで読んでいただき、ありがとうございました。
それでは。
参考記事