gpt4 book ai didi

ruby - 包装类方法的模块?

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

是否可以在不必在类(class)末尾包含模块并将其包含在顶部的情况下完成这项工作?

module VerboseJob
def self.included(job_class)
class << job_class
alias_method :original_perform, :perform
def perform(*args)
JobLogger.verbose { original_perform(*args) }
end
end
end
end

class HelloJob
include VerboseJob

def self.perform(arg1, arg2)
puts "Job invoked with #{arg1} and #{arg2}"
end
end

我想要发生的事情是让 HelloJob.perform 实际调用 VerboseJob.perform(然后调用 block 内的原始方法)。因为这里的模块包含在类的顶部,所以这不起作用,因为 perform 尚未定义。将 include 移到最后确实有效,但有没有更宽容的方法?我喜欢将所有包含的模块放在我的类定义的顶部。

我正在寻找一些在完全加载时在 ModuleClass 上调用的方法,而不是在运行时解释时调用。

最佳答案

这是我想出的一种相当迂回/hackish 的方法,方法是将包装器方法的定义推迟到原始方法定义之后:

module A
def self.included(base)
base.class_eval do
def self.singleton_method_added(name)
@@ran||=false
if name==:perform && !@@ran
@@ran=true
class<<self
alias_method :original_perform, :perform
def perform(*args)
puts "Hello"
original_perform(*args)
end
end
end
end
end
end
end

class B
include A

def self.perform
puts "Foobar"
end
end

B.perform

编辑:

d11wtq 将其简化为更简洁:

module VerboseJob
module ClassMethods
def wrap_perform!
class << self
def perform_with_verbose(*args)
JobLogger.verbose { perform_without_verbose(*args) }
end

alias_method_chain :perform, :verbose \
unless instance_method(:perform) == instance_method(:perform_with_verbose)
end
end

def singleton_method_added(name)
wrap_perform! if name == :perform
end
end

def self.included(job_class)
job_class.extend ClassMethods
job_class.wrap_perform! if job_class.respond_to?(:perform)
end
end

关于ruby - 包装类方法的模块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7189605/

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