コメント機能の実装

commentモデルの作成

rails g model comment body:text user:references board:references

 

アソシエーションの追加(user.rb, board.rb)

has_many comments, dependent: :destroy

 

ルーティングの定義

resources :boards do 

 resources :comments, shallow: true

end

ルーティングをこのように定義することでどのboardに紐付いたcommentかをURLから判別できるようになる。

 

shallow: true

ネストすることによって長くなったURLを短くすることができる。

 

commentsコントローラーの作成

rails g controller comments

class CommentsController < ApplicationController
def create
comment = current_user.comments.build(comment_params)
if comment.save
flash[:success] = "コメントを作成しました"
redirec_to board_path(comment.board)
else
flash[:danger] = 'コメントを作成できませんでした'
redirec_to board_path(comment.board)
end
end

private

def comment_params
params.require(:comment).permit(:body).marge(board_id: params[:board_id])
end
end

 

boards_controller

def show
@board = Board.find(params[:id])
@comment = Comment.new
@comments = @board.comments.includes(:user).order(created_at: :desc)
end
  
viewの作成
comments/_form.html.erb
<div class="row mb-3">
<div class="col-lg-8 offset-lg-2">
<%= form_with model: comment, url: [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 %>
<%= f.submit '作成', class:'btn btn-primary'%>
<% end %>
</div>
</div>
comments/_comments.html.erb
<div class="row">
<div class="col-lg-8 offset-lg-2">
<table id="js-table-comment" class="table">
<%= render comments %>
</table>
</div>
</div>

comments/_comment.html.erb

<%= comment.body %>

boards/show.html.erb

<%= render 'comments/form', { board: @board, comment: @comment }%>
<%= render 'comments/comments', { comments: @comments } %>

掲示板詳細画面の追加

以前作成した掲示板の機能に詳細画面を追加

boards_controller.rb

def show
@board = Board.find(params[:id])
end

 

boards/show.html.erbの作成

 
<article class="card">
<div class="card-body">
 
<h3><%= @board.title %><h3>
<%= @board.created_at %>
</ul>
</div>
</div>
<p><%= @board.body %></p>
</div>
</article>
 
<%= link_to '掲示板一覧', boards_path %>

 

掲示板一覧から詳細画面に遷移できるようにタイトルにlink_toメソッド を使う

<div class="card">
<div class="card-body">
<h4 class="card-title">
<%= link_to board.title, board_path(board) %>
</h4>
<div class="card-body">
<%= board.body %>
</div>
</div>
</div>
 

掲示板の画像アップロード機能

Gemfileに追加

gem  'carrierwave'

gem 'mini_magick'

bundle installする

 

アップローダの作成

rails g uploader Board_Image

board_image_uploader.rbを作成

board_image_uploader.rb

def default_url デフォルトの画像を指定

'.png'

end

def extension_whitelist アップロードできる拡張子を制限

%w(jpg jpeg gir png)

end

 

カラムの追加

マイグレーションファイル

add_column :boards, :board_image, :string

rails db:migrateを実行

 

Boardモデルにアップローダーの宣言

mount_uploader :board_iamge, BoardImageUploader

 

画像の入力フォームを追加

<div class="form-group">

<%= f.label :board_iamge%>

<%= f.file_field :board_image, class:'form-control mb-3', accept: 'image/*' %>

<%= f.hidden_field :board_image_cache %>

</div>

 

画像の表示

<%= image_tag board.board_image_url, class: 'card-img-top', size: '300x200' %>

フォーム入力時エラー情報を個別表示

掲示板作成の時に作ったform_withの中に

<%= render 'shared/_error_messages', object: f.object %>

を追加

 

_error_message.html.erb

<% if object.errors.any? %>
<div class="alert alert-danger>
<ul class="mb-0">
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
form_withから送られてきたobjectにエラーがあれば<%= msg %>で表示される
_error_message.html.erbはパーシャルになっているので以前実装したユーザー登録画面でも利用可能になっている

掲示板作成機能

まずboards_controllerにnewアクション、createアクション、privateメソッドでboard_paramsを作成

def new

@board = Board.new

end

def create

@board = cuurent_user.boards.build(boards_params)

if @board.save

redirect_to boards_path

else

render :new

end

end

private

def board_params

params.require(:board).permit(:title, :body)

end

createアクションの@board = curent_user.boards.build(boards_params)は

current_userのidを持ったBoardを作成できる

 

フォームの作成

<%= form_with model: @board local:true do |f| %>

<%= f.label :title%>

<%= f.text_field :body%>

<%= f.label :body%>

<%= f.text_area :body%>

<% end %>

 

これで実装できました。

掲示板の一覧機能の実装

まずBoardモデルを作成(Userモデルと紐付けるため外部キーを保存できるカラムを設定する)

rails g model Board title:string body:text user:references

rails db:migrate

これでuser_idを保存できるカラムをもったBoardテーブルができました。

 

アソシエーションの設定

Board.rb belongs_to :user

Boardは1つのUserに属しているのでbelongs_to :user(単数形)

 

User.rb has_many :boards, dependent: :destroy

Userは複数のBoardを持っているのでhas_many :boards(複数形)

dependent: :destroy

Userモデルが削除された際に紐付いているBoardも削除する

 

次にバリデーションの設定

validates :title, presence: true, length:{ maximum: 100 }

validates :body, presence: true, length:{ maximum: 100 }

presence 空でないか検証

length:{ maximum: 100 } 値の長さの検証

 

コントローラーの作成

rails g controller boards

class BoardsController < ApplicationController
def index
@boards = Board.all.includes(:user).order(created_at: :desc)
end
end

boards_controllerにindexアクションを作成して上のように取得する

@boardsを取得する際にincludesメソッドをする

includesメソッドを使用する理由はN+1問題を解消するため

 

あとはビューを作れば完成です!

デコレーターの導入

Gemfileに

gem 'draper'

を追加してbundle installする。

 

次にrails g draper:installを実行する

rails g draper:installを実行することによってrails g decorator モデル名が使えるようになる。

rails g decorator Userを実行することによってapp/decoratorsにuser_decoratorが作成される。

class UserDecorator < Draper::Decorator

end
class UserDecorator < Draper::Decorator

def full_name
"#{object.last_name} #{object.first_name}"
end

end

デコレーターにfull_nameメソッドを定義する

 

viewで

<% current_user.decorate.full_name %>

を記述することによって実装できる。