LoginSignup
8
2

More than 5 years have passed since last update.

railsでcheck_boxを複数作りたい場合

Last updated at Posted at 2018-07-28

ruby on rails

例えば、クイズのテーブルがあって、クイズのカテゴリのテーブルもあり、クイズとクイズのカテゴリーは、多対多の関係になっていて、Categorizationという結合テーブルがある場合を考えます。
このような場合において、webサイトの表示にクイズのカテゴリを、チェックボックスで選択したいという課題について考えます。

参考)http://www.tom08.net/entry/2016/09/16/175801
のbefore_saveが大切でした。
自分の場合、before_save :category_ids_slim としました。
before_saveを使わないと、Quizテーブルのcategory_idsのカラムの中身が、
[¥"1¥"]のようになり、利用する際に困ってしまいます。そのため、before_saveが必要となります。
以下、参考ソースコードの紹介

app/model/quiz.rb
class Quiz < ApplicationRecord
  has_many  :categorizations
  has_many  :quiz_categories, through: :categorizations

  before_save :category_ids_slim

  def category_ids_slim
    self.category_ids.gsub!(/[\[\]\"]/, "").gsub!(" ","") if attribute_present?("category_ids")
  end
end

(↑gsubが2つあるのは、苦肉の策です。)

app/views/quiz/edit.html.erb
      <% if @quiz.category_ids.split(",").index("1") %>
        <%= f.check_box :category_ids, {multiple: true, :checked => true}, "1", nil %>
      <% else %>
        <%= f.check_box :category_ids, {multiple: true}, "1", nil %>
      <% end %>
      <%= label_tag :category_ids, '日本史' %>


      <% if @quiz.category_ids.split(",").index("11") %>
        <%= f.check_box :category_ids, {multiple: true, :checked => true}, "11", nil %>
      <% else %>
        <%= f.check_box :category_ids, {multiple: true}, "11", nil %>
      <% end %>
      <%= label_tag :category_ids, '世界史' %>

もちろん、each do 〜 end で繰り返した方がいいのですが、頭の良くない自分は、1つ1つ階段を上がっていく感じでないとプログラムを組めないので、頭の良くない人向けに書いています。
railsでチェックボックスを複数使う場合は、multiple: trueと書きます。すると、@quiz.category_idsの変数が配列として認識されます。
上の内容だと、日本史のチェックボックスにチェックがついていると、1がcategory_idsの配列に追加され、チェックがついてないと何も追加されません。
日本史と、世界史にチェックがついていると、category_idsには、[¥"1¥", ¥"11¥"]のような文字列(配列?)が入ります。(この¥"が邪魔なので、beofre_saveで削除します)
なぜ1と11にしたかというと、@quiz.category_ids.include?("1")とすると、配列に11が入っている場合にも、trueとなってしまうので、それを確認するためです。なので、includeを使うと良くないので、今回は、split(",").index("1")というようにして、解決しています。
リテラルとかenumとかは後で実装します。

ということで、個人的にかなり時間がかかったので、メモついでに書きました。きれいなコードではないと思いますが、参考になるなら見て下さい。他のサイトの解説ではよくわからなかったのと、解説サイトが少なかったので、書きました。

追記

コードのリファクタリング その1 
上のコードをeachで繰り返し処理に変更し、さらにリテラルを排除しました。

app/views/quiz/edit.html.erb
<% QuizCategory.all.each do |c| %>
<% if @quiz.category_ids.split(",").index(c.category_id.to_s) %>
  <%= f.check_box :category_ids, {multiple: true, :checked => true}, c.category_id, nil %>
<% else %>
  <%= f.check_box :category_ids, {multiple: true}, c.category_id, nil %>
<% end %>
<%= label_tag :category_ids, c.name %>
<% end %>
8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2