在所有方法调用之前执行代码

时间:2012-09-06 11:37:12

标签: ruby

我在许多方面仍然对Ruby很陌生,所以尝试这样做有点困难(通过模块?或基类?)。

我想为在类上执行的每个方法调用执行“puts”。类似于黄瓜格式化程序的一种非常简单的形式,即:

class MyClass
    def method_a
        puts 'doing some stuff'
    end 
end

这样输出如下:

MyClass.new.method_a => 'methods_a', 'doing some stuff'

更重要的是,我希望它适用于任何类的任何方法(动态地,不会乱丢我的代码)。我想应用一些格式,即'method_a'=> '方法A'。最好的方法是什么? AOP框架?

3 个答案:

答案 0 :(得分:2)

class MyClass
  def method_a
    puts "Doing A..."
  end

  def method_b
    puts "Doing B..."
  end

  def self.call_before_all_methods
    all_instance_methods = instance_methods - Class.instance_methods
    all_instance_methods.each do |x|
      class_eval <<-END
        alias old_#{x} #{x}
        def #{x}
          print "\'#{x.to_s.split('_').each{|x| x.capitalize!}.join(' ')}\', "
          old_#{x}
        end
        # remove_method old_#{x}.to_sym
      END
    end
  end

  private_class_method :call_before_all_methods
  call_before_all_methods
end

a = MyClass.new
a.method_a
a.method_b

所以这里的技巧是首先为每个方法创建一个别名,然后通过“print formatted method name”+“original method as the alias”重新定义方法。它也由此处文档(&lt;&lt; -END)动态处理。

但是,由于重新定义每种方法都会调用其原始方法,因此最终不可能 remove_method undef 别名。我认为将所有这些别名(old_method_a,ol​​d_method_b)留在那里并不是什么大不了的事。

答案 1 :(得分:0)

你在这里(除了before_filter),即使我不知道你为什么要这样做:

class MyClass
  def puts_all(&blk)
    # get all instance_methods, also including default ones, so remove them by - Class.instance_methods
    all_other_methods = self.class.instance_methods - Class.instance_methods
    # remove the method name itself dynamically by saying __callee__
    all_other_methods.delete(__callee__)
    # formatting as per your need
    all_other_methods.each do |x|
      print "#{x.to_s.split('_').each{|x| x.capitalize!}.join(' ')}, "
      send(x)
    end
  end

  def method_a
    puts "Doing A..."
  end

  def method_b
    puts "Doing B..."
  end

  def another_fancy_method
    puts "Doing fancy..."
  end
end

MyClass.new.puts_all
#=> Method A, Doing A...
#=> Method B, Doing B...
#=> Another Fancy Method, Doing fancy...

因此,要动态实现此功能,您只需使用 instance_methods _ 被调用者 _

答案 2 :(得分:0)

找到答案: How can I intercept method call in ruby?

鉴于它使用继承,它并不理想,但它的效果非常好。