Private class methods in Ruby (the right way)

Augusts Bautra - Mar 13 - - Dev Community

Unfortunately, defining class methods as private is a bit more involved than simply defining them after private.

The incorrect way

module Operations
  private

  def self.private_operation
    "secret"
  end
end

Operations.private_operation #=> "secret" # oh, no!
Enter fullscreen mode Exit fullscreen mode

The correct way

module Operations 
  private_class_method def self.private_operation
    "secret"
  end
end

Operations.private_operation
#=> private method `private_operation' called for Operations:Module (NoMethodError)
Enter fullscreen mode Exit fullscreen mode

It's probably a good practice to place these private class methods right after private, even though it does nothing for them, just to have a consistent class structure:

class Operations 
  def self.public_class_method
    ...

  def public_instance_method
    ...

  private

  private_class_method def self.private_operation
    "secret"  

  def private_instance_method
    ...  
end
Enter fullscreen mode Exit fullscreen mode

The Rails option

Rails' extend ActiveSupport::Concern provides the class_methods block which will honour private definitions:

module Operations
  extend ActiveSupport::Concern

  class_methods do
    def public_operation
      "yay!" + private_operation
    end

    private

    def private_operation
      "secret"
    end
  end
end

includer = Class.new do
  include Operations
end

includer.private_operation
#=> private method `private_operation' called for Class ... (NoMethodError)

includer.public_operation #=> "yay!secret"
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .