ruby-on-rails - define - ruby variables
Ruby on Rails: ¿Dónde definir constantes globales? (12)
A partir de Rails 5.0, puede utilizar el objeto de configuration
directamente para la configuración personalizada :
En config/application.rb
(o config/custom.rb
si lo prefiere)
config.colours = %w(white blue black red green)
Estará disponible como:
Rails.configuration.colours # => ["white", "blue", "black", "red", "green"]
Nota: Para la versión 4.2, necesita usar la propiedad config.x
:
config.x.colours = %w(white blue black red green)
Que estará disponible como:
Rails.configuration.x.colours # => ["white", "blue", "black", "red", "green"]
Estoy empezando con mi primera aplicación web de Ruby on Rails. Tengo un montón de diferentes modelos, vistas, controladores y así sucesivamente.
Estoy deseando 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 para todos mis modelos y también en todos mis puntos de vista.
Para tomar un ejemplo específico, quiero una constante COLOURS = [''white'', ''blue'', ''black'', ''red'', ''green'']
. Esto se usa en todo el lugar, tanto en los modelos como en las vistas. ¿Dónde puedo definirlo en un solo lugar para que sea accesible?
Lo que he intentado:
- Las variables de clase constantes 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 vistaCard.COLOURS
lugar de algo torpe comoCard.first.COLOURS
. - Un método en el modelo, algo así como
def colours [''white'',...] end
- same problem. - 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 realmente no parece correcto (y parece que tampoco funcionan)
¿No hay forma de definir algo para 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 deban referirse al mismo conocimiento específico del dominio?
Algunas opciones:
Usando una constante:
class Card
COLOURS = [''white'', ''blue'', ''black'', ''red'', ''green'', ''yellow''].freeze
end
Lazy cargado usando la variable de instancia de clase:
class Card
def self.colours
@colours ||= [''white'', ''blue'', ''black'', ''red'', ''green'', ''yellow''].freeze
end
end
Si es una constante verdaderamente global ( aunque evite las constantes globales de esta naturaleza ), también podría considerar poner una constante de nivel superior en config/initializers/my_constants.rb
por ejemplo.
De acuerdo con su condición, también puede definir algunas variables ambientales y obtenerlas a través de ENV[''some-var'']
en el código ruby, esta solución puede no ser adecuada para usted, pero espero que pueda ayudar a otros.
Ejemplo: puede crear diferentes archivos .development_env
, .production_env
, .test_env
y cargarlos de acuerdo con sus entornos de aplicación, verifique este gen dotenv-rails que automatiza esto para su.
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 por lo general me mantengo todo constante en estos archivos.
En su caso, puede crear un archivo bajo la carpeta de constantes como colors_constant.rb
colors_constant.rb
No olvides reiniciar el servidor.
La variable global debe declararse en el directorio config/initializers
COLOURS = %w(white blue black red green)
Normalmente tengo una tabla / modelo de ''búsqueda'' en mi programa de rieles y la 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 podría agregar una nueva fila a la tabla de búsqueda y terminar con ella.
Si le otorga a la administración permisos para modificar esta tabla, no vendrán a usted para su mantenimiento. :) SECO.
Aquí es cómo se ve mi código de migración:
class CreateLookups < ActiveRecord::Migration
def change
create_table :lookups do |t|
t.string :group_key
t.string :lookup_key
t.string :lookup_value
t.timestamps
end
end
end
Yo uso seeds.rb para pre-poblarlo.
Lookup.find_or_create_by_group_key_and_lookup_key_and_lookup_value!(group_key: ''development_COLORS'', lookup_key: ''color1'', lookup_value: ''red'');
Otra opción, si desea definir sus constantes en un solo lugar:
module DSL
module Constants
MY_CONSTANT = 1
end
end
Pero aún así, hazlos visibles a nivel mundial sin tener que acceder a ellos de forma totalmente calificada:
DSL::Constants::MY_CONSTANT # => 1
MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT
Object.instance_eval { include DSL::Constants }
MY_CONSTANT # => 1
Para 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. Aún más ... puedes crear diferentes configuraciones para todos tus entornos:
# app/config/application.yml
defaults: &defaults
cool:
saweet: nested settings
neat_setting: 24
awesome_setting: <%= "Did you know 5 + 5 = #{5 + 5}?" %>
colors: "white blue black red green"
development:
<<: *defaults
neat_setting: 800
test:
<<: *defaults
production:
<<: *defaults
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 gama de colores Settings.colors.split(//s/)
. Es muy flexible. Y no necesitas inventar una bicicleta.
Si se necesita una constante en más de una clase, la puse en config / initializers / contant.rb siempre en mayúsculas (la lista de estados a continuación está truncada).
STATES = [''AK'', ''AL'', ... ''WI'', ''WV'', ''WY'']
Están disponibles en toda la aplicación, excepto en el código del modelo como tal:
<%= form.label :states, %>
<%= form.select :states, STATES, {} %>
Para usar la constante en un modelo, use attr_accessor para hacer que la constante esté disponible.
class Customer < ActiveRecord::Base
attr_accessor :STATES
validates :state, inclusion: {in: STATES, message: "-- choose a State from the drop down list."}
end
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:
class Card < ActiveRecord::Base
def self.colours
[''white'', ''blue'']
end
end
# accessible like this
Card.colours
Alternativamente, puede crear variables de clase y un descriptor de acceso. Sin embargo, esto no se recomienda, ya que las variables de clase pueden actuar como algo sorprendente con la herencia y en entornos de subprocesos múltiples.
class Card < ActiveRecord::Base
@@colours = [''white'', ''blue'']
cattr_reader :colours
end
# accessible the same as above
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 verdadera constante inmutable, también puede definirla en la clase modelo:
class Card < ActiveRecord::Base
COLOURS = [''white'', ''blue''].freeze
end
# accessible as
Card::COLOURS
También puede 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 modelo.
# put this into config/initializers/my_constants.rb
COLOURS = [''white'', ''blue''].freeze
Nota: cuando definimos las constantes de arriba, a menudo queremos freeze
la matriz. Eso evita que otro código se modifique más tarde (inadvertidamente) la matriz al agregar, por ejemplo, un nuevo elemento. Una vez que un objeto está congelado, ya no se puede cambiar.
Un lugar común para colocar constantes globales en toda la aplicación es dentro de config/application
.
module MyApp
FOO ||= ENV.fetch(''FOO'', nil)
BAR ||= %w(one two three)
class Application < Rails::Application
config.foo_bar = :baz
end
end
Utilice un método de clase:
def self.colours
[''white'', ''red'', ''black'']
end
Entonces Model.colours
devolverá esa matriz. Alternativamente, cree un inicializador y ajuste las constantes en un módulo para evitar conflictos de espacio de nombres.