ruby-on-rails - define - what is variable ruby




Ruby on Rails: ¿Dónde definir constantes globales? (8)

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 vista Card.COLOURS lugar de algo torpe como Card.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?


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"]

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.


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)

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 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




global