简体   繁体   中英

Augmenting existing methods for all Ruby objects

Often, I see stuff like this:

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

I want to patch Class or Object to have my own version of do_something_to . Doesn't need to do anything fancy, a simple printout of the current time vs time at the beginning and end will do.

Here's a solution that works, except that it doesn't address class-level methods:

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

I think something like this should work.

The do_something_method will save the original method and then redefine the modified one by printing timestamps before and after calling the original method.

Just one caveat. Make sure you call the do_something_to after the method definition, otherwise it'll not find the original method and will fail.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM