Где определить пользовательские типы ошибок в 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 и приведет к сбою проверки.

Надеюсь, это поможет!