Ruby: How to make only one single method in a class public?

Viewed 159

Every discussion of private vs. public Ruby methods in a class shows how to declare all following methods private (or public or protected):

class airplane
  def preflight
  end

  def engine_start
    return unless preflight_complete?
  end

  private

  def preflight_complete?
  end
end

That works great most of the time, where you put all your public methods at the top, and all your private methods down below.

I've got a good-sized class with three public methods, and a few dozen private ones. The private ones are all sequenced in a logical manner for developer comfort.

Now, I find there are 2 or 3 formerly-private methods I need to make public. I don't want to pull them to the top, away from their contextual neighbors. I also find it cludgey to flop back and forth between public and private each time. This is particularly annoying if the screen size pushes the public flag out of view and it's not obvious that a second or third new method are unintentionally public just because I inserted them after the loner public method.

So, is there a graceful way to avoid flopping public/private back and forth to make just one method public?

3 Answers

Just put public (or private, protected) at the start of the method definition:

class airplane
  def preflight
  end

  def engine_start
    return unless preflight_complete?
  end

  private

  def preflight_complete?
  end

  public def tanks_full?
  end

  def pilot_authorized?
  end
end

In this case, pilot_authorized? is still private, but anyone chan check tanks_full?

As an alternative, you can publish this method via a public wrapper.

class airplane
  def preflight
  end

  def engine_start
    return unless preflight_complete?
  end

  def tanks_full?
    _tanks_full?
  end

  private

  def preflight_complete?
  end

  def _tanks_full?
  end

  def pilot_authorized?
  end
end

This way your code is still clearly divided into two sections, without any surprise defectors, and the method is still near its contextual neighbors.

This seems the most readable to me:

class Example
    def public_method1
    end

    private def used_by_public_method1
    end
    
    private def also_used_by_public_method1
    end

    def public_method2
    end
        
    private def used_by_public_method2
    end

    def public_method3
    end
end
Related