記事の内容
コメント機能(comment)をajaxを使って部分的に遷移させる方法で実装しました。更新機能を実装した際に、つまづいたところを残します。
開発環境
Ruby 2.7.2
Rails 6.0.3.4
内容
postに紐づく、コメント(comment)の内容(body)を更新する。
コントローラーは、このような感じです。
class CommentsController < ApplicationController
def update
@comment = current_user.comments.find(params[:id])
if @comment.update(comment_update_params)
render json: @comment , status: :ok
else
render json: { comment: @comment, errors: { messages: @comment.errors.full_messages } }, status: :bad_request
end
end
private
def comment_update_params
params.require(:comment).permit(:body)
end
end
jsのコードはこのような感じです。
$(function() {
// 一部抜粋
$.ajax({
type: 'PATCH',
url: '/comments/' + commentId,
data: {
comment: {
body: body
},
},
dataType: 'json',
}).done(function (data) {
//成功処理
}).fail(function () {
//失敗処理
});
})
});
コメントの更新が成功すると、成功処理が行われます。
しかし、422エラーが発生したしまいました。Railsのログを確認すると以下のようになっていました。
Processing by CommentsController#update as JSON
Parameters: {"comment"=>{"body"=>"あああ"}, "id"=>"36"}
Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Allocations: 834)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
Can't verify CSRF token authenticity.
と記載があります。
どうやら、CSRFトークンが付与されていなかったのが原因らしいです。
application.html.erb
でcsrf_meta_tags
を記載していました。
<!DOCTYPE html>
<html>
<head>
<title> タイトル </title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
CSRFの対応策として記載するものらしいです。詳しくは↓Railsガイドをご確認ください。
Railsセキュリティガイド
これを踏まえ、CSRFトークンを付与する形で以下のようにコードを追加しました。
$(function() {
// 一部抜粋
$.ajax({
type: 'PATCH',
url: '/comments/' + commentId,
data: {
comment: {
body: body
},
},
//追記ここから
headers: {
'X-CSRF-Token' : $('meta[name="csrf-token"]').attr('content')
},
//追記ここまで
dataType: 'json',
}).done(function (data) {
//成功処理
}).fail(function () {
//失敗処理
});
})
});
そしたら正常に動きました。
所感
PCは正直者です。指示されたものしか受け取りません(笑)
書き方は他にもあると思います。以下のRailsガイドを参考にしてみてもいいかもしれません。
Railsガイド Ajax CSRFトークン