所以我正在制作一个宝石,我已经有了很好的投入。不幸的是,它有一个非常重要的错误。不幸的是,如果您有一个回调或与该类的public_methods同名的事件,这个gem会创建可以附加回调的事件。这是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
创建方法对象,其符号:add
不引用公共方法add
,而是使用方法在那个班级之外?
答案 0 :(得分: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
类创建调用as:
non_bugged_instance = DemoClass.new :some_method
bugged_instance = DemoClass.new :some_private_method
但我真诚地建议使用第一个选项。
答案 1 :(得分: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