gpt4 book ai didi

Ruby:如何 Hook 类方法

转载 作者:数据小太阳 更新时间:2023-10-29 07:36:23 25 4
gpt4 key购买 nike

发件人:http://cheind.blogspot.com/2008/12/method-hooks-in-ruby.html

我有

# Contains methods to hook method calls
module FollowingHook

module ClassMethods

private

# Hook the provided instance methods so that the block
# is executed directly after the specified methods have
# been invoked.
#
def following(*syms, &block)
syms.each do |sym| # For each symbol
str_id = "__#{sym}__hooked__"
unless private_instance_methods.include?(str_id)
alias_method str_id, sym # Backup original
# method
private str_id # Make backup private
define_method sym do |*args| # Replace method
ret = __send__ str_id, *args # Invoke backup
block.call(self, # Invoke hook
:method => sym,
:args => args,
:return => ret
)
ret # Forward return value of method
end
end
end
end
end

# On inclusion, we extend the receiver by
# the defined class-methods. This is an ruby
# idiom for defining class methods within a module.
def FollowingHook.included(base)
base.extend(ClassMethods)
end
end

然后我有一个这样的类:

class User
def self.get
#class method
end
def name
#instance method
end
end

在另一个位置/文件中,我重新打开 User 类并连接到它

class User
include FollowingHooks # include the hook module
following :name do |receiver, args|
#do something. This works!!
end
following :get do |reciever, args|
#do something. THIS DOESNT WORK
# Which is to be expected looking at the FollowingHooks module definition.
end
end

连接到任何实例方法都有效。然而,尝试 Hook 类方法没有任何作用,我明白了,因为 FollowingHooks 模块没有实现它。我将如何为类方法实现 Hook ?我完全没有头绪。

最佳答案

您需要在 Class 上包含 FollowingHook 代码,然后调用 following 以便它应用于类方法。

Class.send(:include, FollowingHook)
class User
class << self
following :get do |reciever, args|
# Your awesome code here
end
end
end

编辑:

这是我遵循这个建议的完整工作解决方案:

# Contains methods to hook method calls
module FollowingHook

module ClassMethods

private

# Hook the provided instance methods so that the block
# is executed directly after the specified methods have
# been invoked.
#
def following(*syms, &block)
syms.each do |sym| # For each symbol
str_id = "__#{sym}__hooked__"
unless private_instance_methods.include?(str_id)
alias_method str_id, sym # Backup original
# method
private str_id # Make backup private
define_method sym do |*args| # Replace method
ret = __send__ str_id, *args # Invoke backup
block.call(self, # Invoke hook
:method => sym,
:args => args,
:return => ret
)
ret # Forward return value of method
end
end
end
end
end

def self.included(base)
base.send(:extend, FollowingHook::ClassMethods)
end
end

class User
def self.foo
puts "foo"
end
def bar
puts "bar"
end
end

# You can put this in the class << self block if you prefer that the
# methods only be available on the User class.
Class.send(:include, FollowingHook)

class User
include FollowingHook
following :bar do |receiver, args|
puts receiver.inspect
end
class << self
# If you prefer only the User class include FollowingHooks, use the
# following instead of including them in Class.
# include FollowingHook
following :foo do |receiver, args|
puts receiver.inspect
end
end
end

User.foo #=>
# foo
# User
User.new.bar #=>
# bar
# #<User:0x338d9d>

关于Ruby:如何 Hook 类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15147965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com