-1

所以我正在制作一颗宝石,并且我已经对此有很大的投入。不幸的是,它有一个非常重要的错误。这个 gem 创建事件,你可以将回调附加到,不幸的是,如果你有一个回调或一个与类的 public_methods 同名的事件,它就会出错。这是 gem 的 bug 的一个工作示例,它下面有一些测试代码:

# 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

有没有办法让私有方法使用不引用公共方法to_method的符号创建方法对象,而是使用该类之外的方法?:addadd

4

2 回答 2

1

以下代码演示了通过初始化程序将“main”中定义的方法传递给类的示例。

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 回答