Rails问题:渲染:new后对象验证错误消失
问题
模型类中已实现验证逻辑:
class Department < ApplicationRecord has_many :employees, dependent: :destroy validates :name, presence: true, length: { minimum: 3, maximum: 50 } end
验证功能正常,无法创建未提供名称的Department对象,但视图模板中无法获取错误信息:
Error-Messages: <%= @department.errors.full_messages.size %> <% if @department.errors.any? %> <% @department.errors.full_messages.each do |message|%> <h3><%= message %> </h3> <% end %> <% end %> <%= render "form", department: @department %>
视图中错误信息数量始终显示为0。
控制器代码:
def new @department = Department.new end def create @department = Department.create(department_params) if @department.save puts "-- Positive --" redirect_to departments_path else puts "-- Negative --" puts @department puts @department.errors.full_messages puts "Error message: #{@department.errors.full_messages.size}" puts " ------------ " render :new end end
控制台输出显示控制器中错误信息正常:
-- Negative -- #<Department:0x0000000109b59398> Name can't be blank Name is too short (minimum is 3 characters) Error message: 2 ------------
但视图中错误集合为空,请问问题出在哪里?该如何修复?
原因分析
问题出在create方法的逻辑上:
Department.create(department_params)会尝试创建记录,失败后返回带有错误信息的对象- 紧接着调用
@department.save会重新触发一次完整验证,Rails会在每次调用save/valid?时重置错误集合并重新验证,此时对象已经处于未通过验证的状态,再次验证会清除之前的错误信息,导致渲染视图时错误集合为空。
修复方案
有两种可行的修复方式:
方式一:改用new + save
修改create方法,先初始化对象再调用save,避免重复触发验证:
def create @department = Department.new(department_params) if @department.save puts "-- Positive --" redirect_to departments_path else puts "-- Negative --" puts @department puts @department.errors.full_messages puts "Error message: #{@department.errors.full_messages.size}" puts " ------------ " render :new end end
方式二:用persisted?判断是否创建成功
如果保留create方法,改用persisted?判断对象是否被持久化,避免调用save触发重复验证:
def create @department = Department.create(department_params) if @department.persisted? puts "-- Positive --" redirect_to departments_path else puts "-- Negative --" puts @department puts @department.errors.full_messages puts "Error message: #{@department.errors.full_messages.size}" puts " ------------ " render :new end end
核心逻辑是:避免在create之后再次调用save,防止错误集合被重置,这样视图就能正确获取到验证失败的错误信息。
内容的提问来源于stack exchange,提问作者cluster1
相关产品推荐
相关产品推荐

