Reputation: 11072
In the Spree framework, the Product
model defines a private method called build_variants_from_option_values_hash
.
This method is normally called internally by an after_create
callback, and it is declared as private
within the class. I would like to use of this method outside of the normal "create" lifecycle and call it directly to, however since it is declared privately, unfortunately it is not visible outside of the class.
Question: Is there a way to alter / modify the visibility of a method without redefining it?
Using class_eval
, I can redefine the method in a product decorator outside of the private
area, and this does do the trick. However, I feel like completely copying over an entire method simply to change its visibility is an unnecessary "monkey patching"-type approach. Is there a better way to accomplish this?
Upvotes: 0
Views: 302
Reputation: 16507
Approach with redefining visibility of a method in ruby
is not good. But however you are able to do this by getting and redefining the same method to public space as follows:
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
but the proper way to invoke the private method is to use #send
public method as follows:
object.send :private_method, *args
Upvotes: 1
Reputation: 35350
Though @МалъСкрылевъ's approach is more sensible, IMO, you could alternatively create a public alias of the method:
Product.class_eval do
alias_method :public_build_variants, :build_variants_from_option_values_hash
public :public_build_variants
end
which could now be used as
p = Product.new
p.public_build_variants
Upvotes: 1