在Ruby和/或Rails中定义自定义错误类型的位置?

cor*_*ard 141 ruby ruby-on-rails conventions

是否有在Ruby库(gem)或Ruby on Rails应用程序中定义自定义错误类型的最佳实践?特别:

  1. 他们在结构上属于哪个项目?在其他地方有一个单独的文件,内联相关的模块/类定义?
  2. 有没有建立任何时候约定,当创建一个新的错误类型?

不同的图书馆有不同的做事方式,我没有注意到任何真实的模式.有些库总是使用自定义错误类型,而有些库根本不使用它们; 有些错误扩展了StandardError而其他错误有嵌套层次结构; 有些只是空类定义,有些则有各种巧妙的技巧.

哦,只是因为我觉得调用这些"错误类型"有点含糊不清,我的意思是:

class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end
Run Code Online (Sandbox Code Playgroud)

Mik*_*wis 213

对于宝石

我已经多次看到你用这种方式定义异常:

gem_dir/LIB/gem_name/exceptions.rb

并定义为:

module GemName

  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end

end
Run Code Online (Sandbox Code Playgroud)

这个例子在httparty中是这样的

对于Ruby on Rails

将它们放在名为exceptions.rb的文件下的lib /文件夹中,它看起来像这样:

module Exceptions
  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end
end
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它:

raise Exceptions::InvalidUsername
Run Code Online (Sandbox Code Playgroud)

  • 为什么将它们命名为`Exceptions`模块? (35认同)
  • 我认为`/ lib`可能不是错误的地方.它们是非常特定于应用程序的,我认为我在`/ lib`中放入的代码是可以在其他应用程序中重用的代码. (12认同)
  • Ruby on Rails 说明对我不起作用——在典型情况下是否需要一些额外的步骤来实际加载这个新文件? (2认同)
  • @ABMagil 似乎我必须否则“无法自动加载常量异常,预计 /app/lib/exceptions.rb 来定义它”,我认为另一个选项是每个异常一个类 (2认同)

Dea*_*ffe 25

我认为为了在你的项目中拥有有凝聚力的源文件,你应该在类中定义可能抛出它们而不是其他地方的错误.

一些层次结构可能会有所帮助 - 名称空间很好地保留了多余的字符串名称 - 但这更多的是品味 - 如果您的应用程序中至少有一个自定义异常类型可用于区分,则无需过分在"故意"和"意外"例外情况之间.

  • 虽然理论上你是对的,但是在完全不同的情况下,不同类别可以引发同样的错误会发生什么? (8认同)

sch*_*pet 22

在rails中你可以创建app/errors目录

# app/errors/foo_error.rb
class FooError < StandardError; end
Run Code Online (Sandbox Code Playgroud)

重新启动弹簧/服务器,它应该拿起它


Mat*_*att 10

这是一个古老的问题,但是我想分享一下我如何在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
Run Code Online (Sandbox Code Playgroud)

测试(最小)

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
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

运行验证时,此方法将背负到ActiveRecord的ActiveRecord::RecordInvalid错误类上,并导致验证失败。

希望这可以帮助!


spy*_*yle 9

为确保自动加载在Rails 4.1.10中按预期在多个自定义错误类中工作,您需要为每个自定义错误类指定单独的文件.这应该在动态重新加载的开发中工作.

这是我在最近的项目中设置错误的方法:

lib/app_name/error/base.rb

module AppName
    module Error
        class Base < StandardError; end
    end
end
Run Code Online (Sandbox Code Playgroud)

以及随后的自定义错误,例如 lib/app_name/error/bad_stuff.rb

module AppName
    module Error
        class BadStuff < ::AppName::Error::Base; end
    end
end
Run Code Online (Sandbox Code Playgroud)

然后,您应该可以通过以下方式调用错误:

 raise AppName::Error::BadStuff.new("Bad stuff just happened")
Run Code Online (Sandbox Code Playgroud)