Rails中嵌套模型Post的presence存在性校验不触发如何解决
问题描述
创建Post功能运行正常。
我有父模型Conversation及其子/嵌套模型Post。
当我未输入任何内容点击「Create Post」时,预期应当抛出「Body can't be blank」的错误提示,实际却返回了另一个错误:
相关代码
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 %>
解决方案
你遇到的问题是由几处代码疏漏共同导致的,按以下步骤修改即可:
- 修正Post模型的校验规则
你在post.rb中写的validates :body, presence: :true存在语法错误,presence对应的校验值应为布尔值true而非符号:true,修改为:
validates :body, presence: true
- 完善控制器保存失败的处理逻辑
当前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
- 修改会话详情页的表单传参
你当前在conversations/show.html.erb中渲染表单时固定传递了新的Post实例,会覆盖控制器返回的带错误的@post对象,修改为:
<%= render partial: "posts/form", locals: { conversation: @conversation, post: @post || Post.new } %>
- 修正表单错误信息渲染逻辑
_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
相关产品推荐
相关产品推荐

