In C #, it is legal to do such things:
public class Test { public void Method() { PrivateMethod(); } private void PrivateMethod() { PrivateStaticMethod(); } private static void PrivateStaticMethod() { } }
Is it possible to do something similar in Ruby?
Yes:
class Test def method private_method() end def self.greet puts 'Hi' end private_class_method :greet private def private_method self.class.class_eval do greet end end end Test.new.method Test.greet
But ruby ββdoes not strictly respect confidentiality. For instance,
class Dog def initialize @private = "secret password" end end puts Dog.new.instance_variable_get(:@private) --output:-- secret password
ruby gives you freedom of access to private things with little effort:
Test.new.method Test.class_eval do greet end --output:-- Hi Hi
In ruby, a private method means that you cannot explicitly specify the recipient for the method, that is, there cannot be a name and a dot to the left of the method. But in ruby, a method without a receiver implicitly uses self as a receiver. Therefore, to call a private method, you just need to create a context where self is the correct recipient. Both class_eval and instance_eval change themselves inside the block to the receiver, for example
some_obj.instance_eval do #Inside here, self=some_obj #Go crazy and call private methods defined in some_obj class here end
You can apply these rules to this situation:
(ahmy wrote:) First let me try to explain why the code does not work class MyModel < ActiveRecord::Base def self.create_instance model = MyModel.new
The "context of this" and the "scope" are what a headache. All you need to remember: you cannot call a private method with an explicit receiver. The init_some_dependencies method has been defined as a private method, but it has a "model". written to his left. This is an explicit receiver. Explosion! Error.
Here is the solution:
class MyModel def self.create_instance
Or, as ahmy and LBg pointed out, you can use Object # send () to call private methods:
class MyModel def self.create_instance model = MyModel.new model.send(:init_some_dependencies, 10, 20) end private def init_some_dependencies(*args) puts "Dependencies have been initialized with: #{args}!" end end MyModel.create_instance