2012-04-03 2 views
2

Я ищу способ соединения методов. У меня есть следующий код:Обнаружение, когда метод является цепным

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, как мне это сделать?

ответ

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 может украсить себя.

1

В общем, вы не хотите заботиться (и в большинстве случаев вы даже не добираетесь до знаете), если ваши методы вызываются определенным образом. Таким образом, безумие. Магические последовательности вызовов делают чертовски время отладки и тестирования.

Что вы могли бы сделать, хотя ... вместо do_a return self, оберните вокруг него декоратор, который определяет do_b, и верните декоратор. В этот момент ваш исходный MyClass не может do_b, потому что он не знает, как это сделать. Но вещь вернулась с do_a может.

(Теперь, вы можете сказать, как a = test.do_a, а затем a.do_b, но вы не можете обойти, что без разбора Рубиновый код самостоятельно.)

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), но это только делает его более гибким;)

+0

Проблема в том, что мне все еще нужно иметь доступ к объекту. –

+0

Что значит доступ к объекту? – Jwosty

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, если вы хотите принять определенные действия, основанные на стеке вызовов. Тем не менее, вы можете получить удар в лицо другим разработчиком, если у вас нет веских оснований для этого, LOL.