检测方法链接的时间

时间:2012-04-03 22:07:01

标签: ruby

我希望做一些方法链接。我有以下代码:

class MyClass

  attr_accessor :handler

  def do_a
    puts 'i just did a'
    self.handler = 'a'
    self
  end

  def do_b_if_a
    puts 'i just did b' if handler == 'a'
  end

 end

以下是有效的:

irb > test = MyClass.new
=> #<MyClass:0x007fa44ced9a70 @handler=nil>
irb > test.do_a
'i just did a'
irb > test.do_a.do_b_if_a
'i just did a'
'i just did b'

我不想工作的是当我第一次设置处理程序时调用do_a,这意味着现在可以随时调用do_b_if_a。但我只想在与do_a链接时调用它,我该怎么做?

4 个答案:

答案 0 :(得分:1)

一般情况下,如果以某种方式调用方法,您不想关心(在大多数情况下,您甚至不会知道)。那种方式就是疯狂。魔术呼叫序列可以进行调试和测试。

你可以做什么,但是......而不是让do_a返回self,在它周围包装一个定义do_b的装饰器,然后返回装饰器。此时,您的原始MyClass无法do_b,因为它不知道如何。但是从do_a返回的东西可以。

(现在,您仍然可以说a = test.do_a然后a.do_b,但如果不自行解析Ruby代码,就无法解决这个问题。)

答案 1 :(得分:0)

正如cHao所说,你不应该尝试方法调用模式。但我也可以想到另一种方法:

def do_a
  puts "i just did a"
  do_b_if_a(true)
end

def do_b_if_a(did_a=false)
  puts "i just did b" if did_a
end

do_a       # prints "i just did a"
do_b_if_a  # does nothing

当然,你可以致电do_b_if_a(true),但之后它会让它更灵活;)

答案 2 :(得分:0)

我认为你在错误的地方追踪状态。使用与ActiveRecord的查询界面类似的东西会更好,例如:

class MyClass
  attr_accessor :handler

  def do_a
    puts 'i just did a'
    with_handler 'a'
  end

  def do_b_if_a
    puts 'i just did b' if handler == 'a'
  end

private

  def with_handler(h)
    o = dup
    o.handler = h
    o
  end

end

这样你总是有一个MyClass的实例,但是你有一个可以跟踪其历史记录的丢弃副本。这与cHao's方法类似,但它不需要额外的装饰器类,因为MyClass可以自己修饰。

答案 3 :(得分:0)

不能让你一直到那里,但你可以将do_b_if_a定义为在调用to_a时添加的单例方法:

class MyClass

  def do_a
    puts 'i just did a'
    self.tap{|s| def s.do_b_if_a; puts 'i just did b' end}
  end

 end

如果您想根据调用堆栈执行某些操作,可以查看Kernel.caller。但是,如果你没有充分的理由,你可能会被另一位开发人员搞砸了,哈哈。