ran*_*its 42 ruby rest activerecord ruby-on-rails
我很难理解如何让Rails为渲染XML模板时验证失败的子资源显示明确的错误消息.假设我有以下几个类:
class School < ActiveRecord::Base
has_many :students
validates_associated :students
def self.add_student(bad_email)
s = Student.new(bad_email)
students << s
end
end
class Student < ActiveRecord::Base
belongs_to :school
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:message => "You must supply a valid email"
end
Run Code Online (Sandbox Code Playgroud)
现在,在控制器中,假设我们想构建一个简单的API,允许我们在其中添加一个带有学生的新学校(再次,我说,这是一个可怕的例子,但为了问题的目的发挥作用)
class SchoolsController < ApplicationController
def create
@school = School.new
@school.add_student(params[:bad_email])
respond_to do |format|
if @school.save
# some code
else
format.xml { render :xml => @school.errors, :status => :unprocessable_entity }
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在验证工作正常,因为电子邮件与Student类中的validates_format_of方法中设置的正则表达不匹配而死亡.但是我得到的输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>Students is invalid</error>
</errors>
Run Code Online (Sandbox Code Playgroud)
我想要上面设置的更有意义的错误消息,并显示validates_format_of.意思是,我想说:
<error>You must supply a valid email</error>
Run Code Online (Sandbox Code Playgroud)
为了不出现,我做错了什么?
Har*_*tty 75
在School模型中添加验证块以合并错误:
class School < ActiveRecord::Base
has_many :students
validate do |school|
school.students.each do |student|
next if student.valid?
student.errors.full_messages.each do |msg|
# you can customize the error message here:
errors.add_to_base("Student Error: #{msg}")
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在@school.errors将包含正确的错误:
format.xml { render :xml => @school.errors, :status => :unprocessable_entity }
Run Code Online (Sandbox Code Playgroud)
注意:
您不需要使用单独的方法将新学生添加到学校,请使用以下语法:
school.students.build(:email => email)
Run Code Online (Sandbox Code Playgroud)
errors.add_to_base 已从Rails 3.0及更高版本中删除,应替换为:
errors[:base] << "Student Error: #{msg}"
Run Code Online (Sandbox Code Playgroud)
更新Rails 5.0.1
您可以使用Active Record Autosave Association
class School < ActiveRecord::Base
has_many :students, autosave: true
validates_associated :students
end
class Student < ActiveRecord::Base
belongs_to :school
validates_format_of :email,
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i,
:message => "You must supply a valid email"
end
@school = School.new
@school.build_student(email: 'xyz')
@school.save
@school.errors.full_messages ==> ['You must supply a valid email']
Run Code Online (Sandbox Code Playgroud)
参考:http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
这还不是一个公共API,但Rails 5 stable似乎必须在两个模型之间ActiveModel::Errors#copy!合并errors.
user = User.new(name: "foo", email: nil)
other = User.new(name: nil, email:"foo@bar.com")
user.errors.copy!(other.errors)
user.full_messages #=> [ "name is blank", "email is blank" ]
Run Code Online (Sandbox Code Playgroud)
再次,这还没有正式发布(我在猴子修补Errors课之前偶然发现了这个),我不确定它会是什么.
所以这取决于你.