Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

233
Views
¿Por qué las notaciones compactas y anidadas para clases/módulos en Ruby se comportan de manera diferente?

Estaba mirando la regla de Rubocop para las notaciones de especificación de módulo/clase, y existen estas dos opciones:

 # Style/ClassAndModuleChildren: EnforcedStyle: compact module M::C # Style/ClassAndModuleChildren: EnforcedStyle: nested module M class C

Los siguientes dos archivos, cuando se ejecutan, muestran que los dos no tienen un comportamiento idéntico (consulte el final de cada archivo para ver los resultados de salida):

 # nested.rb # Style/ClassAndModuleChildren: EnforcedStyle: nested module OuterModule def foo; puts 'foo'; end end module OuterModule module InnerModule def hello puts 'hello' end end end module OuterModule class C include InnerModule end end # Does not produce any error when run

 # compact.rb # Style/ClassAndModuleChildren: EnforcedStyle: compact module OuterModule def foo; puts 'foo'; end end module OuterModule module InnerModule def hello puts 'hello' end end end class OuterModule::C include InnerModule end =begin ❯ ruby compact.rb Traceback (most recent call last): 1: from compact.rb:15:in `<main>' compact.rb:16:in `<class:C>': uninitialized constant OuterModule::C::InnerModule (NameError) Did you mean? OuterModule::InnerModule end

¿Por qué es esto?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Es debido a un proceso llamado constan lookup . Cuando Ruby encuentra un token constante como InnerModule , necesita encontrar su valor asignado. Para ello, comprueba el "anidamiento" actual con Module.nesting .

nesting devuelve una matriz de módulos en los que estamos anidados actualmente, pero solo se puede modificar con las palabras clave class y module (y no tiene absolutamente nada que ver con self , lo que puede ser un poco confuso). Cada palabra clave antepone el módulo que estamos abriendo (y solo ese módulo) al anidamiento:

 Module.nesting #=> [] module A class B Module.nesting #=> [A::B, A] end end module A::C Module.nesting #=> [A::C] sic! no A end module A D = Class.new do Module.nesting #=> [A] sic! no module/class keyword = no nesting end end

Entonces, al buscar cualquier constante, Ruby las buscará en los "espacios de nombres" de Module.nesting y sus módulos incluidos (y, si no se encuentra nada, en Object , que es el espacio de nombres superior de Ruby).

Esta es la razón por

 class OuterModule::C include InnerModule end

No funciona. Ruby solo busca la constante InnerModule en OuterModule::C y el espacio de nombres global.

También es bueno saber que las nuevas constantes siempre se definen en el primer espacio de nombres de Module.nesting , no self . Este es un problema bastante común que veo en las pruebas RSpec:

 RSpec.describe SomeClass do EXAMPLES = [1,2,3,4,5] ... end

Aunque Rspec.describe crea una nueva clase en la que se evalúa el bloque dado, no hay una palabra clave module/class lo que significa que todas las constantes definidas dentro de ese bloque son globales . Entonces, si alguna vez encontró una gran dosis de "la definición constante / anterior ya inicializada estaba aquí" al ejecutar una prueba, lo más probable es que se deba a eso.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!