Где определить пользовательские типы ошибок в Ruby и/или Rails?
Существует ли наилучшая практика для определения пользовательских типов ошибок в библиотеке Ruby (gem) или Ruby on Rails? В частности:
- Где они принадлежат структурно в проекте? Отдельный файл, связанный с соответствующим определением модуля/класса, где-то еще?
- Существуют ли какие-либо соглашения, устанавливающие, когда и когда не создавать новый тип ошибки?
В разных библиотеках есть разные способы делать вещи, и я не заметил никаких реальных шаблонов. Некоторые библиотеки всегда используют собственные типы ошибок, а другие вообще не используют их; некоторые из них имеют все ошибки, распространяющие StandardError, в то время как другие имеют вложенные иерархии; некоторые из них - просто пустые определения классов, другие - всевозможные умные трюки.
О, и только потому, что я чувствую, что называть эти "типы ошибок" является своего рода неоднозначным, я имею в виду следующее:
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
Ответы
Ответ 1
Для драгоценных камней
Я видел много раз, что вы определяете исключения таким образом:
gem_dir/Library/gem_name/exceptions.rb
и определяется как:
module GemName
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
end
примером этого будет что-то вроде этого в httparty
Для Ruby on Rails
Поместите их в папку lib/под файлом с именем exceptions.rb, который будет выглядеть примерно так:
module Exceptions
class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
end
и вы будете использовать его следующим образом:
raise Exceptions::InvalidUsername
Ответ 2
Я думаю, что для того, чтобы иметь совлокальные исходные файлы в вашем проекте, вы должны определить ошибки в классе, в котором их можно выбросить, и нигде больше.
Некоторая иерархичность может быть полезна - пространства имен хороши для хранения избыточных строк из имен типов - но это больше зависит от вкуса - нет необходимости переходить за борт, если у вас есть хотя бы один настраиваемый тип исключения в приложении, которое вы используете чтобы различать "преднамеренные" и "случайные" случаи исключения.
Ответ 3
Чтобы гарантировать, что автозагрузка работает как ожидается в Rails 4.1.10 для нескольких пользовательских классов ошибок, вам нужно указать отдельные файлы для каждого. Это должно работать в разработке с его динамической перезагрузкой.
Вот как я устанавливаю ошибки в недавнем проекте:
В lib/app_name/error/base.rb
module AppName
module Error
class Base < StandardError; end
end
end
и в последующих пользовательских ошибках, например, в lib/app_name/error/bad_stuff.rb
module AppName
module Error
class BadStuff < ::AppName::Error::Base; end
end
end
Затем вы можете вызвать свои ошибки с помощью:
raise AppName::Error::BadStuff.new("Bad stuff just happened")
Ответ 4
в рельсах вы можете сделать каталог app/errors
# app/errors/foo_error.rb
class FooError < StandardError; end
перезагрузите spring/сервер, и он должен забрать его
Ответ 5
Это старый вопрос, но я хотел бы поделиться тем, как я обрабатываю пользовательские ошибки в Rails, включая прикрепление сообщений об ошибках, тестирование и способы их устранения с помощью моделей ActiveRecord
.
Создание пользовательской ошибки
class MyClass
# create a custome error
class MissingRequirement < StandardError; end
def my_instance_method
raise MyClass::MissingRequirement, "My error msg" unless true
end
end
Тестирование (minitest)
test "should raise MissingRequirement if ____ is missing"
# should raise an error
error = assert_raises(MyClass::MissingRequirement) {
MyClass.new.my_instance_method
}
assert error.message = "My error msg"
end
С ActiveRecord
Я думаю, стоит отметить, что если работать с моделью ActiveRecord
, популярный шаблон - это добавить ошибку в модель, как описано ниже, чтобы ваши проверки не сработали:
def MyModel < ActiveRecord::Base
validate :code_does_not_contain_hyphens
def code_does_not_contain_hyphens
errors.add(:code, "cannot contain hyphens") if code.include?("-")
end
end
Когда выполняются проверки, этот метод будет возвращаться в класс ошибок ActiveRecord ActiveRecord::RecordInvalid
и приведет к сбою проверки.
Надеюсь, это поможет!