速攻でラベルのモッグを作りたい時のためにメモ
rails new
$ rails _5.2.4_ new sample-relation -d postgresql --skip-bundle && cd sample-relation && bundle install && rails db:create
scaffoldで無駄なファイルが生成されないよう設定
/config/application.rb
module SampleRelation
class Application < Rails::Application
# ここから下を追加
config.generators do |g|
g.javascripts false
g.helper false
g.test_framework false
end
end
end
postテーブル(投稿機能機能)をscaffoldで生成
$ rails g scaffold post title:string details:string
labelテーブル(ラベル機能)をscaffoldで生成
$ rails g scaffold label title:string
post_labelテーブル(postとlabelの中間)をmodelを生成
$ rails g model post_label post:references label:references
アソシエーション
親
post.rb
class Post < ApplicationRecord
has_many :post_labels, dependent: :destroy, foreign_key: 'post_id'
has_many :labels, through: :post_labels, source: :label
end
中間
post_label.rb
class PostLabel < ApplicationRecord
belongs_to :post, optional: true
belongs_to :label, optional: true
end
子(ラベル)
label.rb
class Label < ApplicationRecord
has_many :post_labels, dependent: :destroy, foreign_key: 'label_id'
has_many :posts, through: :post_labels, source: :post
end
コントローラー
パラメータにlabel_idsを追加
posts_controller.rb
private
def post_params
params.require(:post).permit(:title, :details, label_ids: [] )
end
ビュー
新規投稿画面
views/posts/new.html.erb
<%= form_with(model: post, local: true) do |form| %>
<% if post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.post :title %>
<%= form.text_field :title %>
</div>
<div class="field">
<%= form.post :details %>
<%= form.text_field :details %>
</div>
# 追加
<div class="field">
<% Label.all.each do |label| %>
<% if action_name == 'new' || action_name == 'create' %>
<%= form.check_box :label_ids, { multiple: true, checked: label[:checked], disabled: label[:disabled], include_hidden: false}, label[:id], "" %>
<label><%= label.title %></label>
<% elsif action_name == 'edit' || action_name == 'update' %>
<%= form.check_box :label_ids, { multiple: true, checked: @task.label_ids.include?(label.id), disabled: label[:disabled], include_hidden: false}, label[:id], "" %>
<label><%= label.title %></label>
<% end %>
<% end %>
</div>
# ここまで
<div class="actions">
<%= form.submit %>
</div>
<% end %>
投稿一覧画面
views/posts/index.html.erb
<p id="notice"><%= notice %></p>
<h1>Posts</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<% post.post_labels.each do |post_label| %>
<%= post_label.label.title %><br>
<% end %>
<td><%= post.title %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New post', new_post_path %>
めんどくさがりな方のためにラベルのシードデータの設定
seeds.rb
5.times do |i|
Label.create!(title: "sample#{i + 1}")
end
migrate(テーブルをDBに反映)してseedデータを作ってrails s(サーバー起動)
$ rails db:migrate && rails db:seed && rails s
以上です!
追記
編集時にラベルのチェックを全部外したのにupdateされなかったのでその修正
posts_controller.rb
def update
unless params[:task][:label_ids]
@task.label_on_tasks.delete_all
end
respond_to do |format|
if @task.update(task_params)
format.html { redirect_to @task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: @task }
else
format.html { render :edit }
format.json { render json: @task.errors, status: :unprocessable_entity }
end
end
end