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とチェーンされている場合にのみ呼び出されるようにしたいのですが、どうすればよいですか?

4

4 に答える 4

1

一般に、メソッドが特定の方法で呼び出されているかどうかは気にしないでください(ほとんどの場合、知ることすらできません)。そのように狂気があります。魔法の呼び出しシーケンスは、デバッグとテストに非常に時間がかかります。

ただし、何ができるか... do_areturnを使用する代わりに、selfを定義するデコレータをその周りにラップして、デコレータdo_bを返します。その時点で、あなたのオリジナルMyClassはできませんdo_b、それは方法がわからないからです。しかし、物事は缶から戻ってきましたdo_a

(今でも、「いいね」と言ってから「いいね」と言うことはできますが、Rubyコードを自分で解析せずにa = test.do_aそれa.do_bを回避することはできません。)

于 2012-04-03T22:17:20.747 に答える
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)が、それはそれをより柔軟にするだけです;)

于 2012-04-03T22:27:21.677 に答える
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のアプローチに似ていますが、MyClassがそれ自体をデコレートできるため、追加のデコレータクラスは必要ありません。

于 2012-04-03T22:45:46.177 に答える
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を確認できます。ただし、正当な理由がない場合は、別の開発者に殴られる可能性があります(笑)。

于 2012-04-04T02:39:32.180 に答える