Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

269
Visualizações
How different ways to define a class influence the way include works?

I have a simple module that defines a constant and makes it private:

module Foo
  Bar = "Bar"
  private_constant :Bar
end

I can include it in a class like this, and it works as expected:

class User
  include Foo

  def self.test
    Bar
  end
end

puts User.test
# => Bar

begin
  User::Bar
rescue => exception
  puts "#{exception} as expected"
  # => private constant Foo::Bar referenced as expected
end

(let's call it "typical class" definition)

Then I tried the Class.new approach, but this failed miserably:

X = Class.new do
  include Foo

  def self.test
    Bar # Line 28 pointed in the stack trace
  end
end

begin
  X::Bar
rescue => exception
  puts "#{exception}"
  # => private constant Foo::Bar
end

puts X.test
# test.rb:28:in `test': uninitialized constant Bar (NameError)
#         from test.rb:28:in `<main>'

Why? I always though class Something and Something = Class.new are equivalent. What's the actual difference?

Then I had a strike of inspiration, and recalled there's alternative way to define class methods, which actually worked:

X = Class.new do
  class << self
    include Foo
    def test
      Bar
    end
  end
end

begin
  X::Bar
rescue => exception
  puts "#{exception}"
  # => uninitialized constant X::Bar
end

puts X.test
# Bar

Again - why this one work, and why the exception is now different: private constant Foo::Bar vs uninitialized constant X::Bar?

It seems like those 3 ways of initializing classes differ in a nuanced way.

  1. does exactly what I want: Bar is accessible internally, and accessing it gives exception about referencing private constant.
  2. second gives "ok" exception, but has no access to Bar itself
  3. third has access, but now gives slightly different exception

What is exactly going on in here?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

This is one of the biggest gotchas in Ruby: constant definition scope is partially syntactic, that is, it depends on how the code around it is structured.

module Foo
  Bar = "Bar"
end

Bar is inside a module definition, so it is defined in that module.

class << self
  include Foo
end

Bar gets included inside a class definition, so it is defined in that class.

Class.new do
  include Foo
end

There is no enclosing class or module (this is a normal method call with a block), so the constant is defined at top level.

As for your third error, I believe that is because the constant got defined in the singleton class (that's what class << self is) versus the class itself. They are two separate class objects.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda