Recién estoy comenzando con mi primera aplicación web Ruby on Rails. Tengo un montón de diferentes modelos, vistas, controladores, etc.
Quiero encontrar un buen lugar para pegar definiciones de constantes verdaderamente globales, que se apliquen a toda mi aplicación. En particular, se aplican tanto en la lógica de mis modelos como en las decisiones tomadas en mis puntos de vista. No puedo encontrar ningún lugar SECO para poner estas definiciones donde estén disponibles tanto para todos mis modelos como para todas mis vistas.
Para tomar un ejemplo específico, quiero una constante COLOURS = ['white', 'blue', 'black', 'red', 'green']
. Esto se usa en todo el lugar, tanto en modelos como en vistas. ¿Dónde puedo definirlo en un solo lugar para que sea accesible?
Lo que probé:
- Variables de clase constante en el archivo model.rb con las que están más asociadas, como
@@COLOURS = [...]
. Pero no pude encontrar una forma sensata de definirlo para poder escribir en mis puntos de vista enCard.COLOURS
lugar de algo muy groseroCard.first.COLOURS
. - Un método en el modelo, algo así como el
def colours ['white',...] end
mismo problema. - Un método en application_helper.rb: esto es lo que estoy haciendo hasta ahora, pero los ayudantes solo son accesibles en vistas, no en modelos
- Creo que podría haber intentado algo en application.rb o environment.rb, pero eso no parece correcto (y tampoco parece funcionar)
¿No hay forma de definir algo que sea accesible tanto desde los modelos como desde las vistas? Quiero decir, sé que los modelos y las vistas deben estar separados, pero seguramente en algunos dominios habrá ocasiones en que necesiten referirse al mismo conocimiento específico del dominio.
fuente
Respuestas:
Si su modelo es realmente "responsable" de las constantes, debe pegarlas allí. Puede crear métodos de clase para acceder a ellos sin crear una nueva instancia de objeto:
Alternativamente, puede crear variables de clase y un descriptor de acceso. Sin embargo, esto se desaconseja, ya que las variables de clase pueden ser algo sorprendentes con la herencia y en entornos de subprocesos múltiples.
Las dos opciones anteriores le permiten cambiar la matriz devuelta en cada invocación del método de acceso si es necesario. Si tiene una constante verdaderamente inmutable, también puede definirla en la clase de modelo:
También podría crear constantes globales a las que se pueda acceder desde cualquier lugar en un inicializador como en el siguiente ejemplo. Este es probablemente el mejor lugar, si sus colores son realmente globales y se usan en más de un contexto de modelo.
Nota: cuando definimos las constantes anteriores, a menudo queremos
freeze
la matriz. Eso evita que otro código modifique más tarde (sin darse cuenta) la matriz, por ejemplo, agregando un nuevo elemento. Una vez que un objeto está congelado, ya no se puede cambiar.fuente
config/initializers/my_constants.rb
ruta, recuerde reiniciar el servidor:touch tmp/restart.txt
def self.colours
ejemplo no es ideal. Cada vez que llamedef self.colours
, se devolverá una nueva instancia de la matriz .#freeze
No ayudará en este caso. La mejor práctica es declararlo como una constante de Ruby, en cuyo caso siempre obtendrá el mismo objeto.class Card; COLOURS = ['white', 'blue'].freeze; def self.colours; COLOURS; end; end
Dicho esto, la asignación de una matriz en cualquier idioma puede ser potencialmente problemática; por un lado, está usando memoria sin ninguna razón (buena). Si se carga desde una base de datos y desea almacenar en caché el valor, también se puede usar una variable de instancia de clase, que se puede cargar de forma diferida mediante eldef self.colours
método. Sin embargo, coincidimos en el aspecto de la inmutabilidad.Algunas opciones:
Usando una constante:
Carga diferida usando la variable de instancia de clase:
Si es una constante verdaderamente global ( sin embargo, evite las constantes globales de esta naturaleza ), también podría considerar poner una constante de nivel superior,
config/initializers/my_constants.rb
por ejemplo.fuente
extend
el módulo en la clase para que esté disponible conCard.COLOURS
.extend
no funciona para mí. Al usarinclude
puedo acceder como:Card::COLOURS
/models
. Es mucho mejor si crea un inicializador./models
, pero solo si está dentro de un módulo, por ejemplo,module Constants; COLOURS = ...; end
en un archivo llamadomodels/constants.rb
.A partir de Rails 4.2, puede usar la
config.x
propiedad:Que estará disponible como:
Otro método para cargar la configuración personalizada:
En los rieles 5 y 6 , puede usar el
configuration
objeto directamente para la configuración personalizada, además deconfig.x
. Sin embargo, solo se puede usar para configuraciones no anidadas:Estará disponible como:
fuente
Rails.configuration.colours
más (aunque desearía que no fuera tanto)config
es tan bueno comoconfiguration
. Podríamos esperar obtener un atajo en algún momento :)ApplicationController
si no hay nada más en el medio. Si la constante no está directamente relacionada con los controladores, todavía consideraría una configuración global, etc.Si se necesita una constante en más de una clase, la pongo en config / initializers / contant.rb siempre en mayúsculas (la lista de estados a continuación está truncada).
Están disponibles en toda la aplicación, excepto en el código del modelo como tal:
Para usar la constante en un modelo, use attr_accessor para hacer que la constante esté disponible.
fuente
config/initializers/constants.rb
probablemente sería una mejor opción, sin embargoPara la configuración de toda la aplicación y para las constantes globales, recomiendo usar Settingslogic . Esta configuración se almacena en un archivo YML y se puede acceder desde modelos, vistas y controladores. Además, puede crear diferentes configuraciones para todos sus entornos:
En algún lugar de la vista (prefiero los métodos de ayuda para este tipo de cosas) o en un modelo que puede obtener, por ejemplo, una variedad de colores
Settings.colors.split(/\s/)
. Es muy flexible. Y no necesitas inventar una bicicleta.fuente
Utiliza un método de clase:
Luego
Model.colours
devolverá esa matriz. Alternativamente, cree un inicializador y ajuste las constantes en un módulo para evitar conflictos de espacio de nombres.fuente
Intente mantener todo constante en un solo lugar. En mi aplicación, he creado una carpeta de constantes dentro de los inicializadores de la siguiente manera:
y generalmente mantengo todo constante en estos archivos.
En su caso, puede crear un archivo en la carpeta de constantes como
colors_constant.rb
colors_constant.rb
No olvides reiniciar el servidor
fuente
Otra opción, si desea definir sus constantes en un lugar:
Pero aún así hacerlos visibles globalmente sin tener que acceder a ellos de manera totalmente calificada:
fuente
Un lugar común para colocar constantes globales de toda la aplicación es dentro
config/application
.fuente
Normalmente tengo un modelo / tabla de 'búsqueda' en mi programa rails y lo uso para las constantes. Es muy útil si las constantes van a ser diferentes para diferentes entornos. Además, si tiene un plan para extenderlos, digamos que desea agregar 'amarillo' en una fecha posterior, simplemente puede agregar una nueva fila a la tabla de búsqueda y listo.
Si otorga permisos de administrador para modificar esta tabla, no acudirán a usted para realizar tareas de mantenimiento. :) SECO.
Así es como se ve mi código de migración:
Yo uso seeds.rb para rellenarlo previamente.
fuente
La variable global debe declararse en el
config/initializers
directoriofuente
De acuerdo con su condición, también puede definir algunas variables ambientales y buscarlas
ENV['some-var']
en código ruby, esta solución puede no ser adecuada para usted, pero espero que pueda ayudar a otros.Ejemplo: se pueden crear diferentes archivos
.development_env
,.production_env
,.test_env
y cargarlo según sus entornos de aplicaciones, marque esta generación dotenv-carriles que automatizan esto para su.fuente