게시물에 대한 빈 댓글로 Invalid date가 나왔을 때의 대처법
목적
자작 앱으로 투고에 코멘트를 할 수 있는 기능을 작성.
그 때 나오는 에러의 해결에 시간이 걸렸기 때문에, 해결까지의 생각을 비망록으로서 기사로 했습니다.
환경
windows10 홈
우분투 20.04.1 on WSL2
rails 6.0.3
루비 2.6.6
일어난 현상
빈 주석을 보내면 Invalid date 오류가 발생합니다.
코멘트 모델의 컬럼은 이하에 기재
①뷰를 확인
microposts/show.html.erb
<% @comments.each do |c| %>
<div class="d-flex">
<div class="d-flex">
<%= link_to user_path(c.user) do %>
<%= image_tag c.user.portrait.to_s, size: "40x40" %>
<% end %>
</div>
<div class="d-flex flex-column">
<small class="text-muted"><%= c.user.name %></small>
<div>
<small><%= simple_format(h(c.content)) %></small>
</div>
</div>
</div>
<div class="d-flex flex-row mb-3 border-bottom border-dark">
<div class="d-flex align-items-center">
<small><%= Date.parse(c.created_at.to_s).strftime("%m月%d日") %></small> <%# ここでエラー発生 %>
</div>
<% if c.user.id == current_user.id %>
<%= link_to "削除", micropost_comment_path(@micropost, c), method: :delete, data: {confirm: "コメントを削除しますか?"}, class: "btn btn-sm btn-light ml-2" %>
<% end %>
</div>
<% end %>
일자를 「00월 000일」의 형태로 표시시키는 곳에서 에러가 발생하고 있다.
이 메소드는 다른 페이지에서도 사용하고 있어, 그 때 에러가 나오지 않았기 때문에
다른 부분에 버그가 있었고 여기에 걸려있는 것이 아닐까 생각했습니다.
②바리데이션을 확인
우선은 코멘트 모델의 밸리데이션이 제대로 기술되어 있는지 확인한다.
comment.rb
class Comment < ApplicationRecord
belongs_to :user
belongs_to :micropost
validates :content, presence: true, length: {maximum: 200}
validates :user_id, {presence: true}
validates :micropost_id, {presence: true}
end
모델의 밸리데이션에 문제는 없을 것 같다.
그렇다면 데이터베이스의 NotNull 제약에 뭔가 문제가 있을지도.
참고 : 【Rails】 「테이블의 컬럼에 정의하는 Not Null 제약」과 「모델에 정의하는 밸리데이션(presence: true)」의 거동의 차이.
데이터베이스의 내용을 조사해 본다.
mysql> desc comments;
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| id | bigint | NO | PRI | NULL | auto_increment |
| content | text | NO | | NULL | |
| user_id | bigint | NO | MUL | NULL | |
| micropost_id | bigint | NO | MUL | NULL | |
| created_at | datetime(6) | NO | | NULL | |
| updated_at | datetime(6) | NO | | NULL | |
+--------------+-------------+------+-----+---------+----------------+
6 rows in set (0.03 sec)
제대로 :content 컬럼에 NotNull 제약이 붙어 있는 것을 확인.
아무래도 밸리데이션에 문제는 없는 것 같다.
③콘솔로 확인
다음에 빈 투고가 송신되었을 때의 움직임을 콘솔에서 조사해 본다.
pry(main)> c = Comment.new(user_id:33, micropost_id:76, content:"")
=> #<Comment:0x0000563201d95c18
id: nil,
content: "",
user_id: 33,
micropost_id: 76,
created_at: nil,
updated_at: nil>
pry(main)> c.save!
ROLLBACK
ActiveRecord::RecordInvalid: バリデーションに失敗しました: Contentを入力してください
from /home/XXXXX/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.5/lib/active_record/validations.rb:80:in `raise_validation_error'
content가 빈 코멘트는 제대로 바리데이션으로 걸려 있다.
...응? 그럼 왜 Invalid date 에러가 되는 거야?
빈 코멘트의 인스턴스가 어떤 이유로 create되어 있다고?
④ 컨트롤러를 확인
게시 세부정보 페이지에 댓글을 표시하도록 하려면
코멘트와 마이크로 포스트 두 개의 컨트롤러를 확인합니다.
comments_controller.rb
class CommentsController < ApplicationController
before_action :authenticate_user!
before_action :set_micropost
def create
@comments = @micropost.comments
@comment = @micropost.comments.new(comment_params)
@comment.user = current_user
if @comment.save
flash[:primary] = "コメントしました"
redirect_to @micropost
else
flash.now[:danger] = "コメントを入力してください"
render("microposts/show")
end
end
・・・
(略)
・・・
private
def set_micropost
@micropost = Micropost.find_by(id: params[:micropost_id])
end
def comment_params
params.required(:comment).permit(:content).merge(user_id: current_user.id, micropost_id: params[:micropost_id])
end
end
microposts_controller.rb
def show
@micropost = Micropost.find_by(id: params[:id])
@comments = @micropost.comments
@comment = Comment.new # コメントフォームのインスタンスはmicropost/showで作成
end
마이크로 포스트 컨트롤러에 문제는 없을 것 같다.
그렇게 되면 코멘트 컨트롤러의 create 액션에 원인이 있을 것 같다.
⑤ 원인 판명
create 액션을 보고 최초로 정의한 @comments 그리고 다음에 정의한 @comment
@micropost.comments에 붙어 있다는 것을 깨달았다.
create @comment는 빨리 @micropost.comments로 통합된다.
내장 된 @comment 뷰가 표시하려고하지만,
created_at가 nil이므로 Invalid date 오류가 발생합니다.
즉 @comment 을 정의할 때 @micropost
【변경 전】
comment_controller.rb
・・・
def create
@comments = @micropost.comments
@comment = @micropost.comments.new(comment_params)
@comment.user = current_user
if @comment.save
flash[:primary] = "コメントしました"
redirect_to @micropost
else
flash.now[:danger] = "コメントを入力してください"
render("microposts/show")
end
end
・・・
【변경 후】
comment_controller.rb
・・・
def create
@comments = @micropost.comments
@comment = Comment.new(comment_params) # 変更
@comment.user = current_user
if @comment.save
flash[:primary] = "コメントしました"
redirect_to @micropost
else
flash.now[:danger] = "コメントを入力してください"
render("microposts/show")
end
end
・・・
성공적인 성공.
써 보면 단순한 일이지만 대단한 시간 걸렸습니다.
Reference
이 문제에 관하여(게시물에 대한 빈 댓글로 Invalid date가 나왔을 때의 대처법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/luckylundy/items/28615e5994068de49bc7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)