Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to call a private Class method from an instance in Ruby?

Other than self.class.send :method, args..., of course. I'd like to make a rather complex method available at both the class and instance level without duplicating the code.


UPDATE:

@Jonathan Branam: that was my assumption, but I wanted to make sure nobody else had found a way around. Visibility in Ruby is very different from that in Java. You're also quite right that private doesn't work on class methods, though this will declare a private class method:

class Foo
  class <<self
    private
    def bar
      puts 'bar'
    end
  end
end

Foo.bar
# => NoMethodError: private method 'bar' called for Foo:Class
like image 293
James A. Rosen Avatar asked Aug 21 '08 18:08

James A. Rosen


People also ask

How do you call a private method in Ruby?

Using BasicObject#instance_eval , you can call private method.

How do you call private methods outside the class in Ruby?

It has to be explicitly included on each inherited class, or else the included method will only get called for the parent A . The class_eval block executes within the including class's context, so it's just like opening up the class in your class definition.

Can the instance of a class access its private methods?

private variables and methods can be accessed anywhere from the instance of the class that declares it.


1 Answers

Here is a code snippet to go along with the question. Using "private" in a class definition does not apply to class methods. You need to use "private_class_method" as in the following example.

class Foo
  def self.private_bar
    # Complex logic goes here
    puts "hi"
  end
  private_class_method :private_bar
  class <<self
    private
    def another_private_bar
      puts "bar"
    end
  end
  public
  def instance_bar
    self.class.private_bar
  end
  def instance_bar2
    self.class.another_private_bar
  end
end

f=Foo.new
f=instance_bar # NoMethodError: private method `private_bar' called for Foo:Class
f=instance_bar2 # NoMethodError: private method `another_private_bar' called for Foo:Class

I don't see a way to get around this. The documentation says that you cannot specify the receive of a private method. Also you can only access a private method from the same instance. The class Foo is a different object than a given instance of Foo.

Don't take my answer as final. I'm certainly not an expert, but I wanted to provide a code snippet so that others who attempt to answer will have properly private class methods.

like image 64
Jonathan Branam Avatar answered Oct 14 '22 09:10

Jonathan Branam