Ruby 模块包装一个类方法?

Ruby 模块包装一个类方法?,ruby,module,wrapper,Ruby,Module,Wrapper,有没有可能做到这一点,而不必在课程末尾包含模块,只需在顶部包含模块 module VerboseJob def self.included(job_class) class << job_class alias_method :original_perform, :perform def perform(*args) JobLogger.verbose { original_perform(*args) } end

有没有可能做到这一点,而不必在课程末尾包含模块,只需在顶部包含模块

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
模块详细作业
def包括在内(作业级)

类这里是一种相当迂回/刻薄的方法,我通过将包装器方法的定义推迟到最初的方法被定义之后提出:

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
模块A
def自带(基本)
基本类\u评估do
添加了自定义单例方法(名称)
@@ran | |=错误
如果name==:执行&@@跑
@@然=真

类假设您希望在运行
执行
之前定义所有类,您可能希望使用:

将块转换为Proc对象(并因此在点处绑定它) 并在程序退出时将其注册以执行。如果 注册了多个处理程序,它们以相反的顺序执行 注册登记

产生:

再见残酷的世界


您可能还想看看单元测试框架(如Test::unit或MiniTest)是如何处理任务运行延迟的。

为什么不使用添加的
方法来包装
执行
。。呃。。添加?:)我不确定我是否理解你的意思,我不是这样做的吗?我接受了你的答案(结合这个),并得出了更简洁的答案(无论在哪里执行
include
)。请随意编辑您的答案。我还是会接受的:)@Tapio:对不起,我误解了你的代码。在我看来,这并没有那么粗俗。@d11wtq太棒了,那更干净了!我不确定我是否理解这与我的问题有什么关系,这是关于从包含的模块中“包装”类/实例方法的问题?@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
   def do_at_exit(str1)
     at_exit { print str1 }
   end
   at_exit { puts "cruel world" }
   do_at_exit("goodbye ")
   exit