Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 958
Sean Vikoren Avatar asked Nov 02 '11 19:11

Sean Vikoren


2 Answers

It barely matters to make methods private or protected in Ruby, since you can just call send() to get around them.

If you want zoop to stay protected, use send() like this:

def what
  "it is '#{self.class.send(:zoop)}'"
end
like image 90
Unixmonkey Avatar answered Oct 13 '22 00:10

Unixmonkey


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
like image 44
Sean Vikoren Avatar answered Oct 13 '22 00:10

Sean Vikoren