rubyscopevisibilityclass-methodaccess-specifier

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

Solution

  • 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.