-1

だから私は宝石を作っていて、すでにそれについて素晴らしい意見を持っています。残念ながら、かなり重大なバグがあります。この gem は、コールバックをアタッチできるイベントを作成しますが、残念ながら、クラスの public_methods の 1 つと同じ名前のコールバックまたはイベントがある場合、バグが発生します。下にいくつかのテストコードがある宝石のバグの実際の例を次に示します。

# Portion of gem that causes bug
class DemoClass
  def initialize method_symbol
    @method = to_method(method_symbol)
  end

  def call(*args)
    @method.call(*args)
  end

  def some_private_method
    puts 'the private method was called (still bugged)'
  end

  private

  def to_method(method_symbol)
    # this right here references public methods when I don't want it to
    method(method_symbol)
  end
end

# Outside the gem
def some_method
  puts 'this is an original method being called'
end

def some_private_method
  puts 'the private method was NOT called. Bug fixed!'
end

non_bugged_instance = DemoClass.new(:some_method)
bugged_instance = DemoClass.new(:some_private_method)

non_bugged_instance.call
bugged_instance.call

public method を参照するのではなく、そのクラスの外部にあるメソッドを参照するto_methodシンボルを使用して、プライベートメソッドにメソッドオブジェクトを作成させる方法はありますか?:addadd

4

2 に答える 2

1

次のコードは、「メイン」で定義されたメソッドを初期化子を介してクラスに渡す例を示しています。

class DemoClass
  def initialize method
    @method = method
  end

  def touch *args
    puts 'touch'
    @method.call *args
  end   
end

# Outside the gem
def some_method
  puts 'Unbugged method'
end

def some_private_method
  puts 'Bugged method'
end

non_bugged_instance = DemoClass.new( self.method :some_method )
bugged_instance = DemoClass.new( self.method :some_private_method )

puts "Non bugged touch"
non_bugged_instance.touch

puts "Bugged touch"
bugged_instance.touch

そして出力:

Non bugged touch
touch
Unbugged method
Bugged touch
touch
Bugged method

メソッド名のみを使用したい場合は、クラス初期化子を次のように置き換えます。

def initialize method_name
  @method = Kernel.method method_name
end

そして、クラス作成は次のように呼び出します:

non_bugged_instance = DemoClass.new :some_method
bugged_instance = DemoClass.new :some_private_method

ただし、最初のオプションを使用することを強くお勧めします。

于 2013-10-29T17:14:19.533 に答える
0

どうやら、 の外部でメソッドを参照するには、メソッドDemoClassを使用する必要がありましたsuperclass。どうやら、あなたも参照する必要があります。self.classそうしないと、という名前のパブリックメソッドを呼び出そうとしますsuperclass。全体として、次のようになります。

# Portion of gem that causes bug
class DemoClass
  def initialize method_symbol
    @method = to_method(method_symbol)
  end

  def call(*args)
    @method.call(*args)
  end

  def some_private_method
    puts 'the private method was called (still bugged)'
  end

  private

  def to_method(method_symbol)
    # this right here references superclass methods like it's supposed to
    self.class.superclass.method(method_symbol)
  end
end

# Outside the gem
def some_method
  puts 'this is an original method being called'
end

def some_private_method
  puts 'the private method was NOT called. Bug fixed!'
end

non_bugged_instance = DemoClass.new(:some_method)
bugged_instance = DemoClass.new(:some_private_method)

non_bugged_instance.call
bugged_instance.call
于 2013-10-29T15:55:10.460 に答える