ゴール
こういうフォームを作って
{"colors"=>["オレンジ", "イエロー"]}
という風に受け取ることが出来る。
html側
今回は特にモデルを作成するわけではなく、画面でコレクションを生成して投げる形にします。(趣味でhamlで書いてます)
= form_tag '/sample/confirm', method: :post do
- %w(レッド オレンジ イエロー).each do |item|
%label
= check_box_tag 'sample_form[colors][]', item
= item
= submit_tag('送信')
controller側
strong parametersを設定する
private
def post_params
params.require(:sample_form).permit(
colors: []
)
end
配列を受けたい場合はこう。
p post_paramsをすると、colorsに配列が格納されているはず。
collection_check_boxesを使ってみる
izumin5210さんに, collection_check_boxesというview helperがあることを教えて頂いたので、それでも実装してみます。
※ドキュメント的にはどうみてもActiveRecord前提なのですが、DB関係ない画面を想定しているので、ActiveModelを使います。
collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
...
なので、collectionとその要素のvalueとtextに対するアクセサがあれば動きそう。
controller側
サクッとcontroller側でオブジェクトを作ります
class SampleController < ActionController::Base
class Post
include ActiveModel::Model
attr_accessor :colors
end
class Color
include ActiveModel::Model
attr_accessor :name
end
def index
colors = [Color.new(name: 'イエロー'), Color.new(name: 'オレンジ'), Color.new(name: 'ピンク')]
@form = Post.new(colors: colors)
end
def confirm
p post_parms
end
private
def post_parms
params.require(:sample_controller_post).permit(colors: [])
end
end
html側
= form_for @form, url: {action: 'confirm'} do |f|
= f.collection_check_boxes(:colors, @form.colors, :name, :name)
= f.submit('送信')
valueと表示させる内容が一緒なので、nameを渡している。
画面でイエローとピンクを選択して、postし、pした結果はこんな感じ。
{"colors"=>["イエロー", "ピンク", ""]}
まとめ
collection_check_boxesのドキュメントを見ると
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
こういう感じでActiveRecordなオブジェクトを前提にしているのですが、素で書くよりかは短くなりました。
バリデーションかけてリダイレクトして再表示〜とかやろうとすると、paramsからの再構成を考えないといけないですね。それはまたの機会とさせてください。
雑談
Railsでたまに画面を作ると、view helperの使い方を思い出す所からになりますね...