Search code examples
rubyclassmethodsinstanceprotected

How does one access protected class methods from instance methods in Ruby?


I must be missing something about how people do this in Ruby.

If '#protected' is uncommented we get:
in 'what': protected method 'zoop' called for Foo:Class (NoMethodError)

Is there a better way to approach protected class methods?

class Foo
  class << self
    #protected
    def zoop 
      "zoop"
    end
  end
  public
  def what
    "it is '#{self.class.zoop}'"
  end
  protected
end

a = Foo.new
p a.what # => "it is 'zoop'"

I would like zoop to be protected or private (no calling 'Foo.zoop'), but so far, I can't seem to find an elegant way.


Solution

  • Upon further discussions with rue: and drbrain: in ruby-lang, it turns out that my impulse to save memory by placing utility functions at the class level was misplaced.

    In Ruby, the instance methods hang off the class anyway, and the answer is to go ahead and place the utility functions at the instance level as private.

    In summary, a utility function that is accessed only by instance methods:

    class Foo
      def what
        "it is '#{zoop}'"
      end
      private
      def zoop
        "zoop"
      end
    end
    
    p Foo.new.what # => "it is 'zoop'"
    

    For a utility function that needs to be called from instance and class methods, a nested module seemed to be a popular approach:

    class Foo
      module Util
        def self.zoop
          "zoop"
        end
      end
      def what
        "it is '#{Util.zoop}'"
      end
      class << self
        def class_what
          "for all time it is '#{Util.zoop}'"
        end
      end
    end
    
    p Foo.new.what   # => "it is 'zoop'"
    p Foo.class_what # => "for all time it is 'zoop'"
    p Foo::Util.zoop # visible, alas