多対多の関係のPostとCategoryをもつテーブルに置いて、Post編集時に既存のカテゴリに予めチェックボックスをつける方法。form_with model: @post
の形式を使わないと{checked:}
オプションを使えないので少しハマった。
前提:多対多のテーブル構成を実現する
以下を参考にテーブル構成してる前提です。ただし投稿のtitle
は本記事ではname
になってます。
collection_check_boxesの引数に{checked:}
オプションを追加
前段の多対多のテーブルを作成している前提だと、@post.category_ids
で所属カテゴリを配列で取得できるらしい。それに.map(&:to_param)
してやることでチェックが付く。この&:to_param
というのはいつも固定で、@post
やcategory_ids
のようにテーブルやモデルの名称によって変わるものではない。
<%= f.label :category, 'カテゴリ' %>
<%= f.collection_check_boxes(:category_ids, Category.all, :id, :name, { checked: @post.category_ids.map(&:to_param) }) do |category| %>
<%= category.label do %>
<%= category.check_box %>
<%= category.text %>
<% end %>
<% end %>
もしform_with model: @post
で「undefined method 'post_path'」とエラーが出る時
form_with model: @post, url: posts_create_path do
みたいな書き方をしていると{checked:}
オプションは使えない。以下の回答のコメント欄にあるようにresouces
を使わないといけない。
https://teratail.com/questions/200474
本題:最終的なコード
Rails.application.routes.draw do
resources :posts, only: [:new, :create, :edit, :update]
end
class PostsController < ApplicationController
def new
@post = Post.new
end
def create
@post = Post.create(post_params)
redirect_to('/posts/index')
end
def show
@post = Post.find(params[:id])
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id]).update(post_params)
redirect_to("/posts/index")
end
private
def post_params
params.require(:post).permit(:name, category_ids: [])
end
end
<div class="main posts-index">
<div class="container">
<%= form_with model: @post do |f| %>
<p>
<%= f.label :name, 'name'%>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :category, 'カテゴリ' %>
<%= f.collection_check_boxes(:category_ids, Category.all, :id, :name, { checked: @post.category_ids.map(&:to_param) }) do |category| %>
<%= category.label do %>
<%= category.check_box %>
<%= category.text %>
<% end %>
<% end %>
</p>
<%= f.submit '変更を保存' %>
<% end %>
</div>
</div>
その他
Railsはマイグレーションファイルの生成やdb:migrate
を少しでもミスると、特に本番デプロイ時にDBがおかしくなったりするから気をつけてね。一度でもdb:migrate
したら、もうそのマイグレーションファイルは使えないし、schemaを直接書き換えたりしてもダメだよ。
こちらも参考になりそう👇
【Rails】form_with/form_forについて【入門】