create, edit, update, destroyの処理をすべてをAjaxで実装する

掲示板(board)の子モデルのコメント(comment)のcreate、edit、update、destroyのすべてAjaxで実装してみます。

ルーティングは下記のような感じです。

  resources :boards do
    resources :comments, only: [:create, :edit, :destroy, :update]
  end

create、edit、update、destroyのコントローラーの実装

まず、comments_controllerを実装します。リファクタリングは後でやったほうが良い感じですが、とりあえず、動くものを作ることを優先して進めます。

    def create
        @board = Board.find_by(id: params[:board_id])
        @comment = @board.comments.build(comment_params)
        @comment.user_id = current_user.id
        if @comment.save
            @comment = Comment.new
            @comments = @board.comments.page(params[:page]).per(10).order('created_at DESC')
        end
    end

    def edit
        @board = Board.find_by(id: params[:board_id])
        @comment = Comment.find_by(id: params[:id])
    end

    def update
        @board = Board.find_by(id: params[:board_id])
        @comment = Comment.find_by(id: params[:id])
        if @comment.update(comment_params)
            @comments = @board.comments.page(params[:page]).per(10).order('created_at DESC')
        end
    end


    def destroy
        @board = Board.find_by(id: params[:board_id])
        @comment = Comment.find_by(id: params[:id])
        if @comment.destroy
            @comments = @board.comments.page(params[:page]).per(10).order('created_at DESC')
        end
    end

    private
    def comment_params
        params.require(:comment).permit(:content)
    end

コメントを登録したり表示させるViewファイル

コメントを投稿したり、表示させるViewファイルは下記のような感じです。

<div  id="comment_form">
    <%= render "comment_form", board: @board, comment: @comment %> 
</div>

<div id='comment_area'>
    <%= render "comment", comments: @comments %>
</div>

上記のメインのViewファイルから呼び出すパーシャルは下記のような感じです。

_comment_form.html.erbでは、form_forにremote: trueオプションを付けます。これによってcreate.js.erbやupdate.js.erbを読みにいくようになり、Ajax処理ができるようになります。

<%= form_for [board, comment], remote: true do |form| %>
    <%= form.text_area :content%>
    <%= form.submit :送信 %>
<% end %>

_comment.html.erb

<% comments.each do |comment| %>
    <div id="comment_<%= comment.id %>" >
        <%= comment.content %>
    </div>
    <div>
        <%= link_to edit_board_comment_path(board_id: comment.board_id, id: comment.id),remote: true do %>
          <button type='button'><i class='fa fa-clipboard'></i></button>
        <% end %>
    </div>
    <div class="list-inline-item">
        <%= link_to board_comment_path(board_id: comment.board_id, id: comment.id), method: :delete, remote: true do %>
            <i class='fa fa-trash'></i>
        <% end %>
    </div>
<% end %>

Ajax処理の実装

create.js.erb、edit.js.erb、update.js.erb、destroy.js.erbによってJavascriptを使って非同期の動きを実装します。

create.js.erbでは、createメソッドの処理後にid=”comment_area”配下のコメント表示部分を再度読み込み直します。

$('#comment_area').html("<%= escape_javascript(render 'boards/comment', comments: @comments) %>");
$('#comment_form').html("<%= escape_javascript(render 'boards/comment_form', board: @board, comment: @comment) %>");

edit.js.erbでは、編集用のボタンがクリックされたときに、対象コメント(id=”#comment_<%= @comment.id %>“)のテキストエリアをフォーム表示に切り替えます。

$('#comment_<%= @comment.id %>').html("<%= escape_javascript(render 'boards/comment_form', board: @board, comment: @comment) %>");

update.js.erbでは、create.js.erbと同様にコメント表示部分を再読込しています。

$('#comment_area').html("<%= escape_javascript(render 'boards/comment', comments: @comments) %>");

destroy.js.erbでは、destoryメソッド後、create.js.erbなどと同様にコメント表示部分を再読込します。

$('#comment_area').html("<%= escape_javascript(render 'boards/comment', comments: @comments) %>");

実際に実装してみると、色々と手間取りますが、実装できるとかなりサクサク動いてアプリケーションのUXが向上します。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする