地方でリモートワーク in Iwate

東京の受託開発会社でリモートワークしてます。

Railsで複数check_boxを配列で送って、カラムに登録、viewで表示して、checkedもつける方法

スポンサーリンク

f:id:ihatov08:20160916170906j:plain

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