Rails: избавление от универсального X — это недопустимые ошибки проверки

У меня есть форма регистрации, в которой есть вложенные ассоциации/атрибуты, как бы вы их ни называли.

Моя иерархия такова:

class User < ActiveRecord::Base
  acts_as_authentic
  belongs_to :user_role, :polymorphic => true
end

class Customer < ActiveRecord::Base
  has_one :user, :as => :user_role, :dependent => :destroy
  accepts_nested_attributes_for :user, :allow_destroy => true
  validates_associated :user
end

class Employee < ActiveRecord::Base
  has_one :user, :as => :user_role, :dependent => :destroy
  accepts_nested_attributes_for :user, :allow_destroy => true
  validates_associated :user
end

У меня также есть некоторые вещи для проверки в этих классах. Моя проблема в том, что если я пытаюсь создать и Клиент (или Сотрудник и т. д.) с пустой формой, я получаю все ошибки проверки, которые я должен получить, плюс некоторые общие, такие как «Пользователь недействителен» и «Клиент недействителен». Если я повторяю ошибки я получаю что-то вроде:

user.login can't be blank
User is invalid
customer.whatever is blah blah blah...etc
customer.some_other_error etc etc

Поскольку во вложенной модели пользователя есть хотя бы одно недопустимое поле, в список ошибок добавляется дополнительное сообщение «X недопустимо». Это сбивает с толку моего клиента, и поэтому мне интересно, есть ли быстрый способ сделать это вместо того, чтобы самому просматривать ошибки.


person aarona    schedule 01.06.2010    source источник


Ответы (2)


Ответ Салила был почти правильным, но он так и не ответил на 100%. Вот правильный способ сделать это:

def after_validation
    # Skip errors that won't be useful to the end user
    filtered_errors = self.errors.reject{ |err| %{ person }.include?(err.first) }

    # recollect the field names and retitlize them
    # this was I won't be getting 'user.person.first_name' and instead I'll get
    # 'First name'
    filtered_errors.collect{ |err|
      if err[0] =~ /(.+\.)?(.+)$/
        err[0] = $2.titleize
      end
      err
    }

    # reset the errors collection and repopulate it with the filtered errors.
    self.errors.clear
    filtered_errors.each { |err| self.errors.add(*err) }
  end
person aarona    schedule 14.09.2010
comment
Кроме того, я предлагаю запрос функции в качестве лучшего решения, чем этот обходной путь: rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/ - person aarona; 14.09.2010
comment
Я получаю сообщение об ошибке без неявного преобразования символа в строку - person Chemist; 05.11.2014
comment
@Chemist это работало для более старой версии рельсов. Попробуйте отредактировать предоставленный код, чтобы он правильно работал с версией, которую вы сейчас используете. - person aarona; 07.11.2014
comment
@Chemist - чтобы исправить неявное преобразование символа в строку, измените %{} на %w{} - person asgeo1; 11.01.2015
comment
Хотя я заметил, что в Rails 4.1 вам нужно будет использовать массив символов (%i{}) - person asgeo1; 11.01.2015

Используйте метод after_validation

  def after_validation
    # Skip errors that won't be useful to the end user
    filtered_errors = self.errors.reject{ |err| %w{ user User  }.include?(err.first) }
    self.errors.clear
    filtered_errors.each { |err| self.errors.add(*err) }
  end

ОТРЕДАКТИРОВАНО

Примечание:-

Добавьте в следующий список в вашем случае это User или user. вы можете добавить несколько, если у вас есть несколько ассоциаций, разделенных пробелом.

%w{ User user }.include?(err.first) #### This piece of code from the above method has logic which reject the errors which won't be useful to the end user
person Salil    schedule 01.06.2010
comment
Хорошо, это выглядит многообещающе! :) Я думаю, что у вас есть грамматическая ошибка в примечании: - это меня смущает .. Добавьте ... ??? Кроме того, где я должен разместить эту функцию? в каждой модели, которая делает это? Это переопределение функции из ARB? - person aarona; 01.06.2010
comment
извините за грамматику :). поместите этот метод в каждую модель, где вы пишете validates_associated - person Salil; 01.06.2010
comment
Хорошо, я проголосую за вас сейчас, потому что это в основном работает. Одна проблема: вместо этого: Логин слишком короткий (минимум 3 символа) Пароль слишком короткий (минимум 4 символа) Подтверждение пароля слишком короткий (минимум 4 символа) Я получаю следующее: User.login слишком короткий (минимум 3 символа) User.password слишком короткий (минимум 4 символа) Подтверждение User.password слишком короткое (минимум 4 символа). Если вы сможете понять, как это исправить, я приму ваш ответ. - person aarona; 01.06.2010