Невозможно вернуть ошибки, созданные на модели
Я использую gem Responders, но я не могу показать ошибки, которые я создаю на своих моделях, используя erros.add(:base, 'Error message')
,
На моем контроллере, перед respond_with @app
Отладил @app
объект и есть ошибки @app.errors.any?
возвращается true
На мой взгляд, когда я проверяю flash
а также @app
объекты, ни один не имеет ошибки
Контроллер приложений
# app_controllers.rb
def destroy
@app = current_company.apps.find(params[:id])
@app.destroy
respond_with @app
end
Модель приложения
# app.rb
before_destroy :destroy_on_riak
# ...
def destroy_on_riak
# SOME CODE HERE
rescue Exception => e
errors.add(:base, I18n.t("models.app.could_not_destroy", :message => e.message))
return false
end
Вид приложения
# apps.html.haml
-flash.each do |name, msg|
%div{:class => "flash #{name}"}
=content_tag :p, msg if msg.is_a?(String)
Это объект @app перед @app.destroy
"#<ActiveModel::Errors:0x00000004fa0510 @base=#<App id: 34, ...>, @messages={}>"
Это объект @app после @app.destroy
"#<ActiveModel::Errors:0x00000004fa0510 @base=#<App id: 34, ...>, @messages={:base=>[\"Não foi possível excluir a aplicação: undefined method `get_or_new' for #<App:0x00000004f824c0>\"]}>"
Я удалил то, что внутри @base=
для простоты.
4 ответа
Jefflunt правильно, когда один звонит #valid?
очищает массив ошибок: см. https://github.com/rails/rails/blob/4a19b3dea650351aa20d0cad64bf2d5608023a33/activemodel/lib/active_model/validations.rb#L333
Валидаторы на 100% определяют валидность вашего объекта, а не когда вы сами добавляете ошибки для дальнейшего использования.
Пока ActiveRecord переопределяет #valid?
все еще звонит super
: https://github.com/rails/rails/blob/4a19b3dea650351aa20d0cad64bf2d5608023a33/activerecord/lib/active_record/validations.rb#L58
Если вы хотите добавить ошибки и сохранить их, я рекомендую что-то вроде этого:
def failures
@failures ||= []
end
validate :copy_failures_to_errors
def copy_failures_to_errors
@failures.each { |f| errors.add(*f) }
end
Затем измените ваш rescue
:
def destroy_on_riak
# SOME CODE HERE
rescue Exception => e
failures.push([:base, I18n.t("models.app.could_not_destroy", :message => e.message)])
return false
end
Я знаю, что это кажется запутанным, и я знаю, что есть даже примеры онлайн, где люди используют или рекомендуют errors.add(:base, ...)
, но это не безопасный способ хранить и извлекать ошибки на потом.
Кроме того, просто рекомендация, но я советую вам спасти StandardError
и не Exception
если вы абсолютно не должны. Ошибки памяти и тому подобное Exception
s, но каждая нормальная ошибка, которую вы когда-либо хотели бы спасти, должна наследоваться от StandardError
, Просто к вашему сведению.
Я дам вам несколько советов:
Подсказка 1
Ваша форма может звонить valid?
на @app
объект. valid?
метод очищает errors
массив на экземпляре.
Неправильно использовать errors
массив / конструкция вне контекста валидации. Но это МХО.
Подсказка 2
Согласно гему Responders (который я никогда не использовал в прошлом), ваша локаль должна иметь правильную конфигурацию. Пример:
flash:
actions:
create:
notice: "{resource_name} was successfully created"
update:
notice: "{resource_name} was successfully updated"
destroy:
notice: "{resource_name} was successfully destroyed"
alert: "{resource_name} could not be destroyed"
Является ли?
Тайна, кажется, заключается либо в том, что (а) вы не вызываете правильный метод, либо (б) .errors
хеш не содержит того, что вы думаете, что он содержит.
Неправильный метод?
В вашем контроллере вы звоните @app.destroy
, но метод, который добавляет ошибки называется destroy_on_riak
Вы уверены, что не хотите печатать это?
# app_controllers.rb
def destroy
@app = current_company.apps.find(params[:id])
@app.destroy_on_riak # <= The offending line?
respond_with @app
end
Или есть before_destroy
обратный вызов отсутствует в вашем примере кода, который в свою очередь вызывает destroy_on_riak
? Из включенного кода я нигде не вижу, чтобы destroy_on_riak
метод когда-либо вызывается, так что это всего лишь предположение.
Неожиданное содержание .errors
хэш?
Если это не проблема, то когда @app.errors.any?
возвращается true
затем в этой точке кода выведите содержимое @app.errors
в ваш журнал, чтобы вы могли видеть, что не так.
Я должен согласиться с @p.mastinopoulos по этому вопросу. Это действительно должно быть обработано с помощью встроенных проверок. Похоже, вам нужно создать собственный валидатор.
http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html
Попробуйте заменить ваш before_destroy
с validate
:
validate :destroy_on_riak, on: :destroy
Еще не пробовал, но если это не сработает, вы можете рассмотреть возможность создания собственного валидатора, на который есть ссылки в документации.