ruby-on-rails - rails autoload lib
Los rieles no pueden cargar automáticamente la constante del archivo a pesar de estar definidos en ese archivo (2)
Esta es una pregunta difícil de explicar. Tengo un módulo en otro espacio de nombres de módulo así:
# app/models/points/calculator.rb
module Points
module Calculator
def self.included(base)
base.send(:include, CommonMethods)
base.send(:include, "Points::Calculator::#{base}Methods".constantize)
end
end
end
Entonces, en otras clases, todo lo que necesito hacer es:
class User
include Points::Calculator
end
He especificado este directorio en application.rb para que sea auto-cargable ... (aunque creo que los rieles recurren a través de modelos ...)
config.autoload_paths += Dir[ Rails.root.join(''app'', ''models'', "points") ]
En el env del desarrollo, todo funciona bien. Al ejecutar pruebas (y producción env), me sale el siguiente error:
Unable to autoload constant Points::Calculator, expected /Users/pete/work/recognize/app/models/points/calculator.rb to define it (LoadError)
De hecho, seguí los consejos que se indican aquí para solucionar el problema: Evita que Rails descargue un módulo en modo de desarrollo al requerir explícitamente calculator.rb en application.rb.
Sin embargo, ¿por qué sucede esto?
Pegué alguna salida de depuración en el archivo dependencies.rb de ActiveSupport y noté que este archivo se requiere dos veces. La primera vez que se requiere, puedo ver que la constante está cargada.
Pero la segunda vez que se requiere, la constante se ha descargado hasta donde Rails puede decir, pero cuando se llama a la necesidad real, ruby devuelve false porque ruby sabe que ya lo requiere. Luego, Rails lanza el error "no se puede cargar automáticamente a la constante" porque la constante aún no está presente y ruby no "volvió a requerir" el archivo.
¿Alguien puede arrojar luz sobre por qué esto podría estar sucediendo?
Rieles aumenta el mecanismo de búsqueda constante de rubí.
Búsqueda constante en Ruby:
De forma similar al method missing
, se invoca una Module#constant-missing
cuando no se puede resolver una referencia a una constante. Cuando nos referimos a una constante en un ámbito léxico dado, se busca esa constante en:
Each entry in Module.nesting
Each entry in Module.nesting.first.ancestors
Each entry in Object.ancestors if Module.nesting.first is nil or a module.
Cuando nos referimos a una constante, Ruby primero intenta encontrarla de acuerdo con estas reglas de búsqueda integradas.
Cuando ruby no puede encontrar ... Rails entra en acción y usa its own lookup convention
y su conocimiento acerca de las constantes que ya se han cargado (por ruby), Rails anula el Module#const_missing
para cargar las constantes faltantes sin la necesidad de llamadas explícitas de requerimiento por el programador
¿Su propia convención de búsqueda?
El contraste de la carga automática de Ruby (que requiere que la ubicación de cada constante cargada automáticamente se especifique por adelantado) sigue los rieles siguiendo una convención que asigna constantes a los nombres de los archivos.
Points::Calculator # =>points/calculator.rb
Ahora, para la constante de Points :: Calculator, rails busca esta ruta de archivo (es decir, ''points / calculator.rb'') dentro de las rutas de carga automática, definidas por la configuración autoload_paths
.
En este caso, los rieles buscaron points/calculator
ruta de archivo points/calculator
en sus rutas cargadas automáticamente, pero no encuentra el archivo y, por lo tanto, se muestra este error / advertencia.
Esta respuesta es un resumen de este blog de Urbanautomation .
Calculator
debe ser una clase que se carga automáticamente
module Points
class Calculator
...
end
end