如何通过包含模块来包装 Ruby 方法的调用?
当我的某些班级发生某些事情时,我希望收到通知。我想以这样的方式进行设置,使这些类中我的方法的实现不会改变。
我想我会有类似以下模块的东西:
module Notifications
extend ActiveSupport::Concern
module ClassMethods
def notify_when(method)
puts "the #{method} method was called!"
# additional suitable notification code
# now, run the method indicated by the `method` argument
end
end
end
然后我可以将它混合到我的类中,如下所示:
class Foo
include Notifications
# notify that we're running :bar, then run bar
notify_when :bar
def bar(...) # bar may have any arbitrary signature
# ...
end
end
我的主要愿望是我不想修改 :bar
来获取通知工作正常。这可以做到吗?如果是这样,我将如何编写 notify_when
实现?
另外,我正在使用 Rails 3,所以如果有我可以使用的 ActiveSupport 或其他技术,请随时分享。 (我查看了 ActiveSupport::Notifications,但这需要我修改 bar
方法。)
我注意到我可能想使用“模块+超级技巧”。我不确定这是什么——也许有人可以启发我?
I want to be notified when certain things happen in some of my classes. I want to set this up in such a way that the implementation of my methods in those classes doesn't change.
I was thinking I'd have something like the following module:
module Notifications
extend ActiveSupport::Concern
module ClassMethods
def notify_when(method)
puts "the #{method} method was called!"
# additional suitable notification code
# now, run the method indicated by the `method` argument
end
end
end
Then I can mix it into my classes like so:
class Foo
include Notifications
# notify that we're running :bar, then run bar
notify_when :bar
def bar(...) # bar may have any arbitrary signature
# ...
end
end
My key desire is that I don't want to have to modify :bar
to get notifications working correctly. Can this be done? If so, how would I write the notify_when
implementation?
Also, I'm using Rails 3, so if there are ActiveSupport or other techniques I can use, please feel free to share. (I looked at ActiveSupport::Notifications, but that would require me to modify the bar
method.)
It has come to my attention that I might want to use "the Module+super trick". I'm not sure what this is -- perhaps someone can enlighten me?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
自从这里的这个问题一直活跃以来已经有一段时间了,但是还有另一种可能性通过包含(或扩展)的模块来包装方法。
从 2.0 开始,您可以前置模块,有效地使其成为前置类的代理。
在下面的示例中,调用扩展模块 module 的方法,并传递要包装的方法的名称。对于每个方法名称,都会创建一个新模块并添加到前面。这是为了代码简单。您还可以将多个方法附加到单个代理。
与使用
alias_method
和instance_method
(稍后绑定到self
)的解决方案的一个重要区别是,您可以在方法之前定义要包装的方法本身被定义。使用:
It has been quite a while since this question here has been active, but there is another possibility to wrap methods by an included (or extended) Module.
Since 2.0 you can prepend a Module, effectively making it a proxy for the prepending class.
In the example below, a method of an extended module module is called, passing the names of the methods you want to be wrapped. For each of the method names, a new Module is created and prepended. This is for code simplicity. You can also append multiple methods to a single proxy.
An important difference to the solutions using
alias_method
andinstance_method
which is later bound onself
is that you can define the methods to be wrapped before the methods themselves are defined.Use:
我想你可以使用别名方法链。
像这样的事情:
您不必使用这种方法自己修改方法。
I imagine you could use an alias method chain.
Something like this:
You do not have to modify methods yourself with this approach.
我可以想到两种方法:
(1) 装饰
Foo
方法以包含通知。(2) 使用代理对象来拦截对
Foo
的方法调用,并在发生时通知您第一个解决方案是 Jakub 采取的方法,尽管
alias_method
解决方案不是实现此目的的最佳方法是使用此方法:第二个解决方案要求您将
method_missing
与代理结合使用:第一个方法需要修改方法(您说您不想要的东西)和第二种方法需要使用代理,这也许是您不想要的。抱歉,没有简单的解决方案。
I can think of two approaches:
(1) Decorate the
Foo
methods to include a notification.(2) Use a proxy object that intercepts method calls to
Foo
and notifies you when they happenThe first solution is the approach taken by Jakub, though the
alias_method
solution is not the best way to achieve this, use this instead:The second solution requires you to use
method_missing
in combination with a proxy:The first method requires modifying the methods (something you said you didn't want) and the second method requires using a proxy, maybe something you do not want. There is no easy solution I'm sorry.