You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中嵌套模型Post的presence存在性校验不触发如何解决

问题描述

创建Post功能运行正常。
我有父模型Conversation及其子/嵌套模型Post。
enter image description here
当我未输入任何内容点击「Create Post」时,预期应当抛出「Body can't be blank」的错误提示,实际却返回了另一个错误:
enter image description here

相关代码

conversation.rb文件代码

class Conversation < ApplicationRecord
  belongs_to :contact
  has_many :posts
end

post.rb文件代码

class Post < ApplicationRecord
  belongs_to :conversation
  belongs_to :author, polymorphic: true
  has_rich_text :body

  validates :body, presence: :true
end

posts_controller.rb文件代码

class PostsController < ApplicationController
    before_action :authenticate_user!
    before_action :set_conversation

    def create
        @post = @conversation.posts.new(post_params)
        @post.author = current_user
        
       respond_to do |format|
           
           if @post.save
            format.html { redirect_to @conversation }
           end
       end
    end

    private
    def set_conversation
        @conversation = Conversation.find(params[:conversation_id])
    end

    def post_params
        params.require(:post).permit(:body)
    end
end

conversation的show.html.erb代码

<p id="notice"><%= notice %></p>

<p>
  <strong>Subject:</strong>
  <%= @conversation.subject %>
</p>

<p>
  <strong>Contact:</strong>
  <%= link_to @conversation.contact.name, @conversation.contact %>
</p>

<%= link_to 'Edit', edit_conversation_path(@conversation) %> |
<%= link_to 'Back', conversations_path %>

<div id="posts">
 <%= render @posts %>
</div>

<%= render partial: "posts/form", locals: { conversation: @conversation, post: Post.new } %>

Post的局部模板_form.html.erb代码

<%= form_with model: [conversation, post], id: "form" do |form| %>

<div>
 <% form.object.errors.full_messages.each do |message| %>
  <div><%= message %></div>
  <% end %>
</div>

<br>

 <%= form.rich_text_area :body %>

 <%= form.submit %>

<% end %>

解决方案

你遇到的问题是由几处代码疏漏共同导致的,按以下步骤修改即可:

  1. 修正Post模型的校验规则
    你在post.rb中写的validates :body, presence: :true存在语法错误,presence对应的校验值应为布尔值true而非符号:true,修改为:
validates :body, presence: true
  1. 完善控制器保存失败的处理逻辑
    当前create方法只处理了保存成功的分支,保存失败时没有指定渲染的视图,Rails会默认查找不存在的posts/create模板导致报错。修改posts_controller.rb的create方法:
def create
  @post = @conversation.posts.new(post_params)
  @post.author = current_user
  
  respond_to do |format|
    if @post.save
      format.html { redirect_to @conversation }
    else
      # 保存失败时回渲染会话详情页,携带带错误信息的@post实例
      format.html { render "conversations/show" }
    end
  end
end
  1. 修改会话详情页的表单传参
    你当前在conversations/show.html.erb中渲染表单时固定传递了新的Post实例,会覆盖控制器返回的带错误的@post对象,修改为:
<%= render partial: "posts/form", locals: { conversation: @conversation, post: @post || Post.new } %>
  1. 修正表单错误信息渲染逻辑
    _form.html.erb中遍历错误信息的标签使用了<%,不会输出执行结果,改为带输出的<%=:
<div>
 <%= form.object.errors.full_messages.each do |message| %>
  <div><%= message %></div>
  <% end %>
</div>

修改完成后提交空内容就会正常显示"Body can't be blank"的错误提示。


内容的提问来源于stack exchange,提问作者Askar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 01:24:05