rails チェックボックスを自動的に作る collection_check_boxes


初めに

collection_check_boxesというとても便利なものがあると知ったので使ってみました。

例えばカテゴリを選択する際に既に登録されているカテゴリからチェックボックスで選択する場合に使える

使い方

collection_check_boxesについてはrails guidesで

objectが属するクラスのmethodの既存の戻り値をコレクションにしたcheck_boxタグを返します。

だそうです。

使い方としては

<%= collection_check_boxes(:article, :tag_ids, Tag.all, :id, :name) do |tag| %>

  <%= tag.label do %>
    <%= tag.check_box %>
    <%= tag.text %>
  <% end %>

<% end %>

みたいな感じで使えます。

これで既存のタグのチェックボックスが作られます。

実際に使ってみる

まず


rails new qiita_collection_check_boxes

rails g model article title
rails g model tag name
rails g model article_tags article:references tag:references
rails db:migrate

rails g controller articles 

みたいにする

rails routes.rbを

resources :articles 

として

articles_controllerを

class ArticlesController < ApplicationController
  def index
    @articles = Article.all 
  end

  def new 
    @article = Article.new 
  end 

  def create 
    @article = Article.new(article_params)
    if @article.save 
      redirect_to articles_path 
    else 
      render :new 
    end 
  end 

  private 

  def article_params 
    params.require(:article).permit(:title, tag_ids: [])
  end   
end

こんな感じにする。

ここで重要なのがストロングパラメータの

tag_ids: []

のところ

いまいち仕組みが分かっていないんですがcollection_check_boxesでtag_idsを取得してそれが複数の可能性があるから配列にしています。

ただなんでこれで自動的に中間テーブルの作成を行ってくれるのかはわかりません。

ですがとりあえずこれで中間テーブルまで自動的に作成されます。

modelファイルはこんな感じ

article_tag.rb
class ArticleTag < ApplicationRecord
  belongs_to :article
  belongs_to :tag
end

article.rb
class Article < ApplicationRecord
    has_many :article_tags
    has_many :tags, through: :article_tags
end
tag.rb

class Tag < ApplicationRecord
    has_many :article_tags
    has_many :articles, through: :article_tags 
end

これでOK

後はviewを作るのみ

 

new.html.erb
<%= form_with model: @article, local: true do |f| %>
    <%= f.label :title %>
    <%= f.text_field :title %>

    <%= collection_check_boxes(:article, :tag_ids, Tag.all, :id, :name) do |tag| %>
        <%= tag.label do %>
            <%= tag.check_box %>
            <%= tag.text %>
        <% end %>
    <% end %>
    <%= f.submit %>
<% end %>

collection_check_boxesは

objectが属するクラスのmethodの既存の戻り値をコレクションにしたcheck_boxタグを返します。

ということでしたが

Tag.allをしてその一つ一つのid,nameというメソッドの戻り値を取得しています。

tag.labelの中にtag.textと書いていますがこれがtag.nameではうまく動きません。

このあたりもいまいち仕組みが分かってません。

ですがこれで実行すると

こんな感じで既存のタグが出てきてくれます。

おわり