Ruby on 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

Теперь, в контроллере, скажем, мы хотим создать тривиальный 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>

Что я делаю неправильный при этом не обнаружиться?

42
задан randombits 22 April 2010 в 00:55
поделиться

3 ответа

Добавьте блок валидации в модель 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)

Обновление для Rails 3.0+

errors.add_to_base был удален из Rails 3.0 и выше и должен быть заменен на:

errors[:base] << "Student Error: #{msg}"
75
ответ дан 26 November 2019 в 23:37
поделиться

Я вижу проблему в опубликованном коде. add_student - это метод класса класса School , поэтому self будет указывать на объект класса School вместо экземпляра объекта class Школа . Из-за этого строка ученики << s не будет добавлять запись s ​​в запись школа .

Я не знаю, является ли это причиной вашей проблемы с сообщением об ошибке, но я думаю, что это помешает правильной работе кода.

0
ответ дан 26 November 2019 в 23:37
поделиться

Вы должны использовать следующее в 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
0
ответ дан 26 November 2019 в 23:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: