覆盖对象属性访问

时间:2012-08-07 19:20:39

标签: ruby

我想知道是否有可能这样做,如果我有像

这样的东西
class Test

  attr_reader :access_times
  def initialize
    @access_times = 0
  end

  def get_two
    2
  end

  ...
end

t = Test.new

在实际运行方法之前,对t的任何访问都会运行特定的代码吗?

例如,如果我突然决定说t.get_two,我使用.语法的事实会将@access_times增加1.或者我做了一次检查{{1} },它还会将t.is_a?(Test)增加1.访问由@access_times继承的任何方法或属性也会使变量增加1。

基本上我想在可能的情况下为Test语法添加一些内容。

我不是在问这个代码是好还是坏,只是它是否可能以及如何完成。我通常不会使用它,因为我可以手动将增量逻辑添加到每个方法,并用方法替换所有直接实例变量访问(甚至像.和从is_a?继承的其他东西)

3 个答案:

答案 0 :(得分:0)

如果您不需要一切都是独立的,那么建议只是扩展ActiveModel::Callbacks。只需扩展该类,您将拥有before_filter的所有功能,而无需其他所有Rails内容。

答案 1 :(得分:0)

一个漂亮的硬核版本就是使用set_trace_funchttp://apidock.com/ruby/Kernel/set_trace_func

这允许您订阅整个程序中触发的所有ruby事件,这可能是大量的调用......

我认为没有用于注册任意方法调用的内置钩子。你可以用方法缺失,方法链接或委托来实现某些东西,但这取决于你的要求。

答案 2 :(得分:0)

根据您的描述,这是一种解决方法。基本上它会为每个实例方法增加@access_times,并且该方法也会执行以前的操作。

class Test
  attr_accessor :access_times

  def initialize
    @access_times = 0
  end

  def get_two
    2
  end
end

class Test
  @@im = instance_methods

  @@im.each do |m|
    class_eval <<-END
      alias temporary #{m}
    END

    define_method(m) do |*args, &block|
      @access_times += 1
      temporary(*args, &block)
    end
  end

  undef :temporary
end

Test.new.get_two # => @access_times += 1 and original get_two is called: 2

虽然这段代码没有按预期工作,但我稍后会看一下。感谢。