在不重新定义方法的情况下改变方法可见性

时间:2014-12-01 16:51:33

标签: ruby-on-rails ruby ruby-on-rails-4 methods visibility

在Spree框架中,Product模型定义了一个名为build_variants_from_option_values_hash的私有方法。

此方法通常由after_create回调在内部调用,并在类中声明为private。我想在正常情况下使用这种方法"创建"生命周期并直接调用它,但是因为它是私有声明的,不幸的是它在类之外是不可见的。

问题:有没有办法在不重新定义方法的情况下更改/修改方法的可见性?

使用class_eval,我可以在private区域之外的产品装饰器中重新定义该方法,这确实可以解决问题。但是,我觉得完全复制整个方法只是为了改变它的可见性是一种不必要的猴子修补"型方法。有没有更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:1)

虽然@МалъСкрылевъ的方法更明智,IMO,您也可以创建该方法的公共别名:

Product.class_eval do

  alias_method :public_build_variants, :build_variants_from_option_values_hash
  public :public_build_variants

end

现在可以用作

p = Product.new
p.public_build_variants

答案 1 :(得分:1)

重新定义ruby中方法的可见性的方法并不好。但是,您可以通过将相同的方法重新定义到公共空间来完成此操作,如下所示:

class CC
   private
   def private_method
   end
end
CC.new.private_method # => NoMethodError: private method `private_method' called for #<CC:0x8166144>

method = CC.instance_method(:private_method)
CC.send(:remove_method, :private_method)
CC.send(:define_method, :private_method, method)
CC.new.private_method # => nil

但调用私有方法的正确方法是使用#send公共方法,如下所示:

object.send :private_method, *args