Railsの複数check_boxの邪道な使い方です。
userに表示したくないカテゴリを設定するときに、userテーブルにshut_categories_ids
カラム(String型)をもたせて、カンマ区切りの文字列で保存する方法です。
さらに、showページで表示したくないカテゴリの一覧も表示したいです。
editでは表示したくないカテゴリのチェックボックスにcheckedが付いている状態にしたい。
そんな要件を満たす実装方法です。
has_many_thoroughな関係でテーブルと中間テーブルを持たせればselect_collection_boxes
で簡単に実装できるようです。しかし、今回はuserテーブルとcategoryテーブルのみで実装してみたいと思います。
フォーム
formはnewとeditでpartialを使うことを前提にしています。
eachですべてのカテゴリを表示します。
multiple: true
で複数チェックボックスの値を送ることができます。
checkedオプションで@categories変数にカテゴリのオブジェクトが含まれていればtrueが返り、チェックが付くようになっています。
<%= form_for @user do |f| %> <% ProductCategory.all.each do |c| %> <%= f.check_box :shut_categories_ids, { multiple: true, :checked => @categories.present? ? @categories.include?(c) : false, include_hidden: false }, c.id %> <%= c.name %> <% end %> <% end %>
コントローラ
@categoriesにはcontrollerでeditアクションでwhereで該当するカテゴリを探してます。
def show @user = User.find(params[:id]) @shut_categories = ProductCategory.where(id: @user.shut_categories_ids.split(',')) end def edit @user = User.find(params[:id]) @categories = Category.where(id: @user.shut_categories_ids.split(',')) end
結果"shut_categories_ids"=>["1", "2", "3", "4"]
のようなparameterが送られます。
これを受け取るにはstrong paramterで配列を指定してあげる必要があります。
Strong Parameters
def update_params params.require(:user).permit({:shut_categories_ids => []}) end
このままのparameterで保存するとviewで表示するときにうまく扱えないので、before_saveでカンマ区切りの文字列にします。これを使わないと"["1", "2", "3", "4"]"
配列っぽいけどかっこに囲まれた文字列で保存されて扱いにくいです。
こうするとsplitメソッドでidが入った配列に変換しやすいです。
モデル before_save
# model before_save do self.shut_categories_ids.gsub!(/[\[\]\"]/, "") if attribute_present?("shut_categories_ids") end
コメントを残す