Ir para conteúdo principal
Lucas Caton

Why Ruby class methods aren't always private (and how to fix it)

Accidentally exposing methods as public in `class << self` is surprisingly easy

Lucas Caton

Lucas Caton

@lucascaton
Ruby provides multiple ways to define class methods, and one common approach is using the class << self block. However, this syntax has a subtle gotcha: methods defined inside the block are public by default, even if the block is nested within a private section.
This behavior can lead to unintended exposure of class methods that should remain private, making your code less secure or harder to maintain.
Here's an example:
ruby
class MyClass
  private

  class << self
    def my_method # ← this is a public method 😱
      # ...
    end
  end
end

Why does this happen?

When you use class << self, Ruby opens the singleton class of the object (in this case, your class). While methods defined in a normal class body respect the current visibility context (private, protected, or public), class << self resets the default visibility to public. As a result, any method defined there will be public unless explicitly declared otherwise.

Option #1 to fix it: declare private explicitly

Within the class << self block, explicitly set the visibility to private:
ruby
class MyClass
  private

  class << self
    private # ← you have to declare `private` again

    def my_method # ← now this method is actually private!
      # ...
    end
  end
end
By the way, all subsequent methods defined in the block will also be private!

Option #2: use private_class_method

Although I personally don't like this approach, an alternative is to define the class method and then use private_class_method to set its visibility:
ruby
class MyClass
  class << self
    def my_method
      # ...
    end
  end

  private_class_method :my_method
end
Remember this and you'll write more secure and maintainable Ruby code!
💬 Comentários desativados temporariamente. Desculpe pelo inconveniente.