Ruby 向库代码添加模块的首选方法?

发布于 2024-12-11 07:24:57 字数 567 浏览 0 评论 0原文

将模块功能添加到库 ruby​​ 代码的首选方法是什么?

考虑以下问题:

module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end

如何将 MyExceptions 模块添加到我无法控制的类中?


更新,在 my_library_class_exceptions.rb 中我做了:

class LibraryClass
    include MyExceptions
end
module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end

但是控制台返回:NameError:未初始化的常量 LibraryClass::MyExceptions

What's the preferred method to add module functionality to library ruby code?

Consider the following:

module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end

How can I add MyExceptions module to a class that I don't control?


Update, in my_library_class_exceptions.rb I did:

class LibraryClass
    include MyExceptions
end
module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end

But the console returns: NameError: uninitialized constant LibraryClass::MyExceptions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苍白女子 2024-12-18 07:24:57

在 Ruby 中,您可以稍后打开任何类的定义并更改它。

下面是一个人为的示例,用于通过重新打开以前创建的类来覆盖除法以使用自定义异常。

class Foo
  def divide(a, b)
    a/b
  end
end

foo = Foo.new()
foo.divide(1, 0)

module MyExceptions
  class MyDivisionError < StandardError; end
end

class Foo
  include MyExceptions
  alias old_divide divide
  def divide(a, b)
    old_divide(a, b)
  rescue ZeroDivisionError
    raise MyDivisionError
  end
end

foo.divide(1, 0)

In Ruby, you can open the definition of any class later and change it.

Below is a contrived example for overriding division to use a custom exception by reopening a previously created class.

class Foo
  def divide(a, b)
    a/b
  end
end

foo = Foo.new()
foo.divide(1, 0)

module MyExceptions
  class MyDivisionError < StandardError; end
end

class Foo
  include MyExceptions
  alias old_divide divide
  def divide(a, b)
    old_divide(a, b)
  rescue ZeroDivisionError
    raise MyDivisionError
  end
end

foo.divide(1, 0)
最美的太阳 2024-12-18 07:24:57

查看您的更新,它不起作用的简单原因是顺序:您在定义之前使用 MyExceptions。
文件的固定版本 - 重新打开库类:

require 'thelib'

module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end
LibraryClass.class_eval do
    include MyExceptions
end

这个类 eval 技巧可以说是比简单地再次打开类更安全的方法:如果您错过了类名,它会警告您。

顺便说一句:我真的不明白你是如何计划使用 MyException 那么......这可能意味着更多的猴子修补和/或包装库的部分。

更新:上面假设您在同一目录中有thelib.rb,其中至少包含以下内容:

class LibraryClass
end

Looking at your update, the simple reason it doesn't work is the order: you use MyExceptions before it's defined.
The fixed version of your file - reopening the library class:

require 'thelib'

module MyExceptions
    class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
end
LibraryClass.class_eval do
    include MyExceptions
end

This class eval trick is arguably a safer way for reopening class than simply class LibraryClass again: it will warn you if you missed the classname.

BTW: I don't really see how you're planning the use MyException then.. that would probably mean some more monkey patching and/or wrapping parts of the library.

UPDATE: the above assumes you have thelib.rb in the same directory with at least the following content:

class LibraryClass
end
以往的大感动 2024-12-18 07:24:57

我通过修复一些东西并改变一些东西来实现这个工作。

  1. 事实证明,LibraryClass 实际上并不是一个类,而是一个模块。所以我改变了:

    类库类
    包括我的异常
    事实

into to:

module LibraryClass
    module MyExceptions
        class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
    end
end
  1. 然后我将 library_class.rb 移动到 lib\library_class_extensions.rb 中,并确保 lib 是自动加载路径的一部分。
  2. 然后在初始化程序中,我调用 require 'library_class_extensions'

我认为这对于我试图完成的行为来说是一个更好的模式,因为这实际上更多的是 app/model 的库类型代码 输入代码。

我对每个人给出的答案都投了赞成票,感谢他们的英勇努力。

I got this working by fixing a few things, and changing a few things.

  1. It turns out LibraryClass wasn't actually a class, but a module. So I changed:

    class LibraryClass
    include MyExceptions
    end

into to:

module LibraryClass
    module MyExceptions
        class SomethingBadHappenedTheLibarayDesignerDidntConsider < StandardError; end
    end
end
  1. Then I moved library_class.rb into lib\library_class_extensions.rb and made sure that lib was part of the autoload path.
  2. Then in an initializer, I called require 'library_class_extensions'

I think that's a better pattern for the behavior I was trying to accomplish anyway, since this really is more of library type code that app/model type code.

I'm up-voting the answers given by everyone, for their heroic efforts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文