備忘録です!!
##Commentモデル作成
userとboardに紐ずいたcommentモデルを作成します。
ターミナル
rails g model Comment body:text user:references board:references
##他モデルとのアソシエーションを追加
commentモデルとuser,boardモデルとのアソシエーションを追加します。
references型を用いたので、blongs_toは最初から記載されています。
user.rb
has_many :comments, dependent: :destroy
has_many :boards, dependent: :destroy
board.rb
has_many :comments, dependent: :destroy
##ルーティングを追加
今回は、boardのルーティングをネストしていきます。
routes.rb
references :boards, only: %i[index new create show] do
references :comments, only: %i[create], shallow: true
ターミナル
board_comments POST /boards/:board_id/comments(.:format) comments#create
boards GET /boards(.:format) boards#index
POST /boards(.:format) boards#create
new_board GET /boards/new(.:format) boards#new
board GET /boards/:id(.:format) boards#show
shallowをtrueにしてpathを綺麗にします。
##commentコントローラーを作成
ターミナル
rails g controller Comments
comments.controller
def create
comment = current_user.comments.build(comment_params)
comment.board_id = params[:board_id]
if comment.save
redirect_to board_path(params[:board_id]), success: t('defaults.message.created', item: Comment.model_name.human)
else
redirect_to board_path(params[:board_id]), danger: t('defaults.message.not_created', item: Comment.model_name.human)
def comment_params
params.require(:comment).permit(:body, board_id)
コメントが保存できたら、掲示板詳細ページに移動するようにします。
この辺は、掲示板投稿機能の実装とそこまで変わりません。
##boardコントローラー
掲示板の詳細ページでコメントのデータを取得します。
boards.controller
def show
@board = Board.find(params[:id])
@comment = current_user.comment.new
@comments = @board.comments.includes(:user).order(created_at: :desc)
これで、コメントのデータと投稿のデータを取得でき、さらにコメントが、投稿時間順に表示されます。
##viewの追加
viewを追加していきます。
今回は、コメントの表示、コメント投稿フォームはパーシャルで作成していきます。
board/show.html.erb
<div class="container pt-5">
<div class="row mb-3">
<div class="col-lg-8 offset-lg-2">
<h1><%= t('.title') %></h1>
<!-- 掲示板内容 -->
<article class="card">
<div id="broad-id-<%= @board.id %>">
<div class="card-body">
<div class='row'>
<div class='col-md-3'>
<%= image_tag @board.board_image.url, class: 'card-img-top img-fluid', size: '300x200' %>
</div>
<div class='col-md-9'>
<h3 class="d-inline"><%= @board.title %></h3>
<ul class='list-inline float-right'>
<li class="list-inline-item">
<%= link_to '#', id: 'button-edit-#{board.id}' do %>
<%= icon 'fa', 'pen' %>
<% end %>
</li>
<li class="list-inline-item">
<%= link_to '#', id: 'button-delete-#{board.id}', method: :delete, data: {confirm: ''} do %>
<%= icon 'fas', 'trash' %>
<% end %>
</li>
</ul>
<ul class="list-inline">
<li class="list-inline-item">by <%= @board.user.decorate.full_name %></li>
<li class="list-inline-item"><%= l @board.created_at, format: :long %></li>
</ul>
</div>
</div>
<p><%= simple_format(@board.body) %></p>
</div>
</div>
</article>
</div>
</div>
<!-- コメントフォーム -->
<%= render 'comments/form', { board: @board, comment: @comment } %>
<!-- コメントエリア -->
<div class="row">
<div class="col-lg-8 offset-lg-2">
<table id="js-table-comment" class="table">
<%= render partial: 'comments/comment', collection: @comments %>
</table>
</div>
</div>
</div>
comment/_comment.html.erb
<tr id="comment-<%= comment.id %>">
<td style="width: 60px">
<%= image_tag 'sample.jpg', class: 'rounded-circle', size: '50x50' %>
</td>
<td>
<h3 class="small"><%= comment.user.decorate.full_name %></h3>
<div id="js-comment-<%= comment.id %>">
<%= simple_format(comment.body) %>
</div>
</td>
<% if current_user == comment.user %>
<td class="action">
<ul class="list-inline justify-content-center" style="float: right;">
<li class="list-inline-item">
<a href="#" class='js-edit-comment-button' data-comment-id="<%= comment.id %>">
<%= icon 'fa', 'pen' %>
</a>
</li>
<li class="list-inline-item">
<a href="#" class='js-delete-comment-button' data-comment-id="<%= comment.id %>">
<%= icon 'fas', 'trash' %>
</a>
</li>
</ul>
</td>
<% end %>
</tr>
comment/_form.html.erb
<div class="row mb-3">
<div class="col-lg-8 offset-lg-2">
<%= form_with model: [board, comment], local: true do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :body %>
<%= f.text_area :body, class: 'form-control mb-3', id: 'js-new-comment-body', row: 4, placeholder: Comment.human_attribute_name(:body) %>
<%= f.hidden_field :board_id, value: @board.id %>
<%= f.submit t('defaults.post'), class: 'btn btn-primary' %>
<% end %>
</div>
</div>
部分テンプレートの再現性が下がってしまうため、コメントの表示のパーシャルには、インスタンス変数ではなく、ローカル変数を用いました。