Techioz Blog

Rails 7 「Rails 入門」 コメントを検証するための推奨される方法は何ですか?

概要

レールは初めてです。よろしくお願いします。 コメント検証を含む公式 Rails 7 ガイドに記載されているブログの機能を拡張しようとしています。 これはプロジェクト コードの github リポジトリ リンクです。 コメントに検証を追加し、無効なフォームを送信した後にフロントエンドにエラーメッセージを表示する正しい方法は何ですか?

設定 ubuntu - 22.04 RVM-1.29.12 ルビー - 3.1.4p223 レール - 7.0.4.3

現在、コメントモデルにこれらの検証を追加すると、検証が機能しません。空のコメントフォームを送信すると、投稿ページにリダイレクトされるだけです。

/app/models/comment.rb

class Comment < ApplicationRecord
  belongs_to :post
  validates :author, presence: true
  validates :body, presence: true
end

また、comments_controllerでコメントの保存を処理しようとしました。ただし、コメントは空の :author フィールドと :body フィールドとともに保存されます。

/app/controllers/comments_controller.rb

def create
  @post = Post.find(params[:post_id])
  @comment = @post.comments.build(comment_params)
  if @comment.save
    redirect_to @post
  else
    render @post, status: :unprocessable_entity
  end
end

/app/views/comments/_form.html.erb

<%= form_with model: [@post, @post.comments.build] do |form| %>
  <div class="mb-3">
    <%= form.label :author, class: 'form-label' %><br>
    <%= form.text_field :author, class: 'form-control', placeholder: 'John Doe' %>
  </div>
  <div class="mb-3">
    <%= form.label :body, class: 'form-label' %><br>
    <%= form.text_area :body, class: 'form-control', rows: 3 %>
  </div>
  <div class="mb-3">
    <%= form.submit 'Add comment', class: 'btn btn-outline-primary' %>
  </div>
<% end %>

ここに私が達成したい視覚化がいくつかあります(開発ツールを通じていくつかのHTMLを追加しただけです)。最初のスクリーンショット - コメント フォームを送信する前にページを投稿し、ページをクリーンアップするだけです。 2 番目のスクリーンショット (私がハイブしたいもの) - 空の作成者フィールドと本文フィールドを持つコメント フォームを送信した後の同じページ。

最初のスクリーンショット

2 番目のスクリーンショット (これは私が望むコメントフォームです)

解決策

保存が失敗した場合は、CommentsController クラスの作成メソッドに次の 2 つの変更を加えます。

投稿を再取得する必要がある理由は、投稿の表示ビューが (/posts/show.html.erb 内で) 再レンダリングされるときに、表示ビュー内の <%= render @post.comments %> 行が投稿のすべてのコメントをリストします。失敗時にレンダリングする前に再フェッチしない限り、新しい「失敗」コメントが含まれます。

これが解決策の最初の部分です。次に、コメント フォームの上にエラー メッセージを表示し、コメント フォームの作成者と本文に元の値を再入力します。これを実現するには、/posts/show.html.erb で次のことを行う必要があります。

まず、コメント フォーム (

コメントの追加

セクション) をレンダリングするには、次の手順を実行します。

<%= 部分レンダリング: ‘コメント/フォーム’、ローカル: { コメント: @comment } %>

これにより、コメントが使用できるようにコメント部分ビュー (/comments/_form.html.erb) に渡されます。以下は、目的を達成する部分ビューのサンプルです。

<p style="color: red"><%= comment ? comment.errors.full_messages.to_sentence : nil %></p>

<%= form_with model: [ @post, @post.comments.build ] do |form| %>
  <p>
    <%= form.label :author %><br>
    <%= text_field_tag 'comment[author]', comment&.author %>
  </p>

  <p>
    <%= form.label :body %><br>
    <%= text_area_tag 'comment[body]', comment&.body %>
  </p>

  <p>
    <%= form.submit %>
  </p>
<% end %>

セーフ ナビゲーション演算子 (&.) は、オブジェクトが nil かどうかを確認します。したがって、フォームに有効なコメントがある場合 (再レンダリングが失敗した場合にのみ当てはまります)、元のデータが表示されます。そうでない場合、フィールドは空になります。 & も同様に使用できます。構文はエラー メッセージに表示されますが、各プロパティに追加する必要があるため、代わりに「長い」バージョンを残しました。

コメント モデルの検証のいずれかが失敗すると、エラー メッセージが表示され、失敗したコメントの元の内容がそれぞれのフィールドに再入力されます。

コメントエラーの例

最後の「クリーンアップ」として、部分的な @post に直接アクセスするのではなく、ローカルの投稿を /comments/_form.html.erb に渡すことを検討できます。