Rails 4: ¿organizar modelos de rieles en subrutas sin modelos de espacio de nombres?


80

¿Sería posible tener algo como esto?

app/models/
app/models/users/user.rb
app/models/users/education.rb

El objetivo es organizar mejor la carpeta / app / models , pero sin tener que asignar espacios de nombres a los modelos.

Una pregunta sin respuesta para Rails 3 está aquí: Rails 3.2.9 y modelos en subcarpetas .

La especificación de table_name con espacios de nombres parece funcionar (consulte la subcarpeta del modelo Rails 4 ), pero quiero hacer esto sin un espacio de nombres .


Entendí que no desea un espacio de nombres, pero creo que la mejor manera de hacerlo es utilizando ActiveSupport Concerns.
Nando Sousa

2
@NandoSousa. No. Las preocupaciones de ActiveSupport se refieren al comportamiento compartido. La forma en que usa los modelos.
Berkes

Respuestas:


116

De forma predeterminada, Rails no agrega subcarpetas del directorio de modelos a la ruta de carga automática. Es por eso que solo puede encontrar modelos con espacios de nombres: el espacio de nombres ilumina el subdirectorio para buscar.

Para agregar todas las subcarpetas de aplicaciones / modelos a la ruta de carga automática, agregue lo siguiente a config / application.rb :

config.autoload_paths += Dir[Rails.root.join("app", "models", "{*/}")]

O, si tiene un directorio de aplicaciones / modelos más complejo , es posible que el método anterior de agrupar todas las subcarpetas de aplicaciones / modelos no funcione correctamente. En cuyo caso, puede evitar esto siendo un poco más explícito y solo agregando las subcarpetas que especifique:

config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name1>")
config.autoload_paths += Rails.root.join("app", "models", "<my_subfolder_name2>")

ACTUALIZAR para Rails 4.1+

A partir de Rails 4.1, el generador de aplicaciones no incluye config.autoload_pathsde forma predeterminada. Entonces, tenga en cuenta que lo anterior realmente pertenece a config / application.rb .

ACTUALIZAR

Se corrigieron los ejemplos de ruta de carga automática en el código anterior para usar en {*/}lugar de {**}. Asegúrese de leer el comentario de muichkine para obtener detalles sobre esto.


6
Lo intenté pero falla con una constante No se puede cargar automáticamente User :: Credits, se esperaba /srv/books/app/models/user/credits.rb para definirlo. Por lo que todavía no se quieren nombrar los archivos espaciados. Colóquelos encima de la entrada lib como se sugiere.
Rubytastic

1
Este error es realmente una buena noticia. Significa que encontró el archivo. Pero estás usando una pluralización extraña aquí. Si el nombre del archivo es app/models/user/credits.rbentonces asegúrese de que el nombre de la clase en el archivo también es plural: class Credits. Pero, recomendaría usar el estándar Rails y hacer que class Creditel nombre del archivo sea app/models/user/credit.rb(los modelos deben ser en singular). De cualquier manera, este debería ser el problema. ¡Házmelo saber!
pdobb

1
En la configuración de Rails 4.1 que usoconfig.autoload_paths += %W( #{Rails.root}/app/models/namespace #{Rails.root}/app/models/other_namespace )
Epigene

14
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]funciona pero ralentiza la aplicación, especialmente en el modo de desarrollo donde la aplicación se recarga con frecuencia. La razón es que no debe agregar todos los archivos a autoload_paths, sino solo las carpetas raíz de donde se pueden inferir los nombres de archivo y los módulos. En términos simples, si solo tiene un nivel de subcarpetas en modelos y no hay modelos de espacio de nombres, solo debe hacer lo config.autoload_paths += Dir[Rails.root.join('app', 'models', '*/')]que agrega solo el primer nivel de subdirectorios. Lo mismo para libu otros caminos.
muichkine

3
@pdobb es experiencia :) si miras cómo funciona la carga automática, verás que se repite en todos los auto_loading_pathsque agrega la inferencia para el modelo. Por ejemplo, si lo tiene NameSpace::Model, intentará encontrar en todos los autoloading_paths un path/namespace/model. Obviamente, esto solo puede coincidir cuando pathes un directorio. Como regla general, solo debe tener directorios en el autoload_pathspara una máxima eficiencia. Espero eso ayude.
muichkine
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.