Вложенные сообщения об ошибках модели - PullRequest
3 голосов
/ 13 августа 2011

Я использую Ruby on Rails 3.0.9 и пытаюсь проверить вложенную модель.Предположим, что я запускаю проверку для «основной» модели, и это создает некоторые ошибки для вложенной модели, я получаю следующее:

@user.valid?

@user.errors.inspect
# => {:"account.firstname"=>["is too short", "can not be blank"], :"account.lastname"=>["is too short", "can not be blank"], :account=>["is invalid"]}

Как вы можете видеть, что инфраструктура RoR создает хеш errors, имеющий следующие ключи: account.firstname, account.lastname, account.Поскольку я хотел бы отображать сообщения об ошибках на внешнем контенте, обрабатывая эти пары ключ-значение ошибки с помощью JavaScript (кстати: я использую jQuery), который включает в себя свойства CSS, я подумал «подготовить» эти данные и изменить эти ключи на account_firstname, account_lastname, account (примечание: я заменяю . на символ _).

Как изменить значения ключа, например, account.firstnameaccount_firstname?

И, В основном важно , как мне справиться с этой ситуацией?Является ли то, что я пытаюсь сделать "хороший" способ обработки вложенных ошибок модели?Если нет, каков общий \ лучший подход для этого?

Ответы [ 4 ]

4 голосов
/ 05 февраля 2013

Я сделал быстрый Концерн, который показывает полные сообщения об ошибках для вложенных моделей:

https://gist.github.com/4710856

#1.9.3-p362 :008 > s.all_full_error_messages
  # => ["Purchaser can't be blank", "Consumer email can't be blank", "Consumer email is invalid", "Consumer full name can't be blank"]
2 голосов
/ 13 августа 2011

Некоторые творческие исправления хеша ошибок Rails позволят вам достичь вашей цели. Создайте инициализатор в config/initalizers, позвольте назвать его errors_hash_patch.rb и поместите в него следующее:

ActiveModel::Errors.class_eval do
  def [](attribute)
    attribute = attribute.to_sym
    dotted_attribute = attribute.to_s.gsub("_", ".").to_sym
    attribute_result = get(attribute)
    dotted_attribute_result = get(dotted_attribute)
    if attribute_result 
      attribute_result 
    elsif dotted_attribute_result
      dotted_attribute_result
    else
      set(attribute, [])
    end
  end
end

Все, что вы здесь делаете, это просто переопределяете метод доступа [], чтобы попробовать немного сложнее. Более конкретно, если ключ, который вы ищете, имеет подчеркивание, он попытается найти его как есть, но если он не сможет ничего найти, он также заменит все подчеркивания точками и попытается найти это тоже. В остальном поведение такое же, как и у обычного [] метода. Например, допустим, у вас есть хэш ошибок, подобный хешу из вашего примера:

errors = {:"account.firstname"=>["is too short", "can not be blank"], :"account.lastname"=>["is too short", "can not be blank"], :account=>["is invalid"]}

Вот некоторые способы, которыми вы можете получить к нему доступ, и результаты, которые возвращаются:

errors[:account] => ["is invalid"]
errors[:"account.lastname"] => ["is too short", "can not be blank"]
errors[:account_lastname] => ["is too short", "can not be blank"]
errors[:blah] => []

Мы не изменяем способ хранения ключей в хэше ошибок, поэтому мы не будем случайно нарушать библиотеки и поведение, которые могут зависеть от формата хэша. Все, что мы делаем, - это немного разумнее с точки зрения доступа к данным в хэше. Конечно, если вы действительно хотите изменить данные в хэше, шаблон будет таким же, вам просто нужно переопределить метод []=, и каждый раз, когда rails пытается сохранить ключи с точками в них, просто измените точки на подчеркивает.

Что касается вашего второго вопроса, хотя я и показал вам, как делать то, что вы просите, в общем, лучше всего попытаться выполнить то, как рельсы пытаются делать вещи, а не пытаться согнуть рельсы к вашему. будут. В вашем случае, если вы хотите отображать сообщения об ошибках через javascript, возможно, ваш javascript будет иметь доступ к хешу данных об ошибках, так почему бы не настроить эти данные с помощью javascript в нужном вам формате. В качестве альтернативы вы можете клонировать данные об ошибках внутри контроллера и настроить их там (до того, как ваш javascript когда-либо получит к ним доступ). Трудно дать совет, не зная больше о вашей ситуации (как вы пишете свои формы, что именно делает ваша проверка JS и т. Д.), Но это общие рекомендации.

1 голос
/ 03 января 2014

У меня была такая же проблема с AngularJ, поэтому я решил перезаписать метод as_json для класса ActiveModel::Errors в инициализаторе с именем active_model_errors.rb, чтобы он мог заменить . на _

Вот код инициализатора:

module ActiveModel
  class Errors
    def as_json(options=nil)
      hash = {}
      to_hash(options && options[:full_messages]).each{ |k,v| hash[k.to_s.sub('.', '_')] = messages[k] }
      hash
    end
  end
end

Надеюсь, это кому-нибудь пригодится

0 голосов
/ 13 августа 2011

Я не уверен, но я думаю, что вы не можете изменить это поведение без боли. Но вы можете попробовать такие решения, как http://bcardarella.com/post/4211204716/client-side-validations-3-0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...