【问题标题】:Augmenting existing methods for all Ruby objects增强所有 Ruby 对象的现有方法
【发布时间】:2014-06-18 15:34:00
【问题描述】:

我经常看到这样的东西:

class Someclass
 do_something_to :foo, :bar, :class_level

 def foo
   puts "Hi!"
 end

 def bar
 end

 def self.class_level
  puts "Something else!"
 end
end

我想修补ClassObject 以获得我自己的do_something_to 版本。不需要做任何花哨的事情,一个简单的打印输出当前时间与开始和结束的时间就可以了。

这是一个可行的解决方案,只是它不涉及类级别的方法:

require 'aspector'

class Class
  def do_something_to(*names)
    aspector do
      around(names) do |proxy, *args, &block|
        start_time = Time.now.to_f
        proxy.call *args, &block
        final_time = Time.now.to_f - start_time 
        puts final_time
        return final_time
      end
    end
  end
end

class MyClass

  do_something_to :hey, :derp

  def hey
    puts "Hey!"
    sleep 1
  end
  def derp x
    puts x
    sleep 2
  end
end

【问题讨论】:

  • 您是想将您的函数包装在所有方法周围(因此任何方法调用,无论它是什么,都会打印时间戳),还是仅一种特定方法(例如任何具有test 方法的类会在之前和之后打印时间戳)?
  • @DaveMongoose 是的,我只想要指定的那些。我应该提到这一点
  • @waldyr,该参考很有用,但问题似乎略有不同,因为 dsp_099 希望包装器仅适用于特定方法。
  • dsp,之前我曾承诺提供另一种解决方案,但未能实现。我今晚会处理它,但如果您想选择答案,请不要等待。

标签: ruby class metaprogramming


【解决方案1】:

我认为这样的事情应该可行。

do_something_method 将保存原始方法,然后通过在调用原始方法之前和之后打印时间戳来重新定义修改后的方法。

只有一个警告。确保在方法定义后调用do_something_to,否则找不到原来的方法,会失败。

class Class
  def do_something_to(method)

    class_eval <<-EOS, __FILE__, __LINE__ + 1
      alias_method :modified_#{method}, :#{method}
      def #{method}
        puts Time.now.to_i
        modified_#{method}
        puts Time.now.to_i
      end
    EOS

  end
end

class MyClass

  def test_method
    puts "Hello world"
  end

  do_something_to :test_method
end

MyClass.new.test_method
# => 1403105585
# => "Hello world!"
# => 1403105586

【讨论】:

  • 有没有办法避免上述警告?
  • 我现在想不出来,但听起来很难,因为 ruby​​ 会顺序执行这段代码,当调用 do_something_method 时,它需要修改的方法已经存在,就像 alias 一样。
  • 如果 do_something 方法是由 Gem 添加的呢?这会改变什么吗?
  • 我不这么认为。这里的问题是,在您调用 do_something_to 时,您要修改的方法需要存在,这听起来也很自然,不是吗?这就像使用一个变量,你必须在使用它之前声明它。 :)
  • alias_method 不是最好的方法。请参阅您问题的 cmets 中链接的重复问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-28
  • 2011-07-02
  • 1970-01-01
相关资源
最近更新 更多