Мне тяжело понимать, как заставить направляющие показывать явное сообщение об ошибке для дочернего ресурса, который приводит проверку к сбою, когда я представляю шаблон 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
Теперь, в контроллере, скажем, мы хотим создать тривиальный 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
Теперь проверка работает просто великолепно, вещи умирают, потому что электронная почта не соответствует regex, это установлено в validates_format_of методе в Студенческом классе. Однако вывод, который я получаю, следующий:
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>Students is invalid</error>
</errors>
Я хочу более значимое сообщение об ошибке, что я установил выше с validates_format_of для разоблачения. Значение, я хочу, чтобы это сказало:
<error>You must supply a valid email</error>
Что я делаю неправильный при этом не обнаружиться?
Добавьте блок валидации в модель 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
Теперь @school. errors
будет содержать правильные ошибки:
format.xml { render :xml => @school.errors, :status => :unprocessable_entity }
Примечание:
Вам не нужен отдельный метод для добавления нового ученика в школу, используйте следующий синтаксис:
school.students.build(:email => email)
errors.add_to_base
был удален из Rails 3.0 и выше и должен быть заменен на:
errors[:base] << "Student Error: #{msg}"
Я вижу проблему в опубликованном коде. add_student
- это метод класса класса School
, поэтому self
будет указывать на объект класса School
вместо экземпляра объекта class Школа
. Из-за этого строка ученики << s
не будет добавлять запись s
в запись школа
.
Я не знаю, является ли это причиной вашей проблемы с сообщением об ошибке, но я думаю, что это помешает правильной работе кода.
Вы должны использовать следующее в rhtml.
<%= error_messages_for :school, :student %>
Чтобы пропустить сообщение « Student is invalid », используйте следующее в student.rb
def after_validation
# Skip errors that won't be useful to the end user
filtered_errors = self.errors.reject{ |err| %w{ student}.include?(err.first) }
self.errors.clear
filtered_errors.each { |err| self.errors.add(*err) }
end
EDITED
Sorry after_validation must be in a school.rb