Je commence juste avec ma première webapp Ruby on Rails. J’ai un tas de différents modèles, vues, contrôleurs, etc.
Je veux trouver un bon endroit pour coller les définitions de constantes véritablement globales, qui s’appliquent à l’ensemble de mon application. En particulier, elles s’appliquent à la fois dans la logique de mes modèles et dans les décisions sockets dans mes vues. Je ne trouve aucun endroit SEC pour mettre ces définitions là où elles sont disponibles à la fois dans tous mes modèles et dans toutes mes vues.
Pour prendre un exemple spécifique, je veux une constante COLOURS = ['white', 'blue', 'black', 'red', 'green']
. Ceci est utilisé partout, dans les deux modèles et les vues. Où puis-je le définir en un seul endroit pour qu’il soit accessible?
Ce que j’ai essayé:
@@COLOURS = [...]
. Mais je ne pouvais pas trouver un moyen sensé de le définir pour pouvoir écrire dans mes vues Card.COLOURS
plutôt que quelque chose comme Card.first.COLOURS
. def colours ['white',...] end
– même problème. N’y a-t-il aucun moyen de définir quoi que ce soit accessible à la fois à partir de modèles et de vues? Je veux dire, je sais que les modèles et les vues doivent être séparés, mais dans certains domaines, il faudra sûrement parfois se référer aux mêmes connaissances spécifiques à un domaine?
Si votre modèle est vraiment “responsable” des constantes, vous devez les y coller. Vous pouvez créer des méthodes de classe pour y accéder sans créer de nouvelle instance d’object:
class Card < ActiveRecord::Base def self.colours ['white', 'blue'] end end # accessible like this Card.colours
Vous pouvez également créer des variables de classe et un accesseur. Cela est cependant déconseillé car les variables de classe peuvent surprendre avec l'inheritance et dans les environnements multi-thread.
class Card < ActiveRecord::Base @@colours = ['white', 'blue'] cattr_reader :colours end # accessible the same as above
Les deux options ci-dessus vous permettent de modifier le tableau renvoyé à chaque appel de la méthode de l'accesseur si nécessaire. Si vous avez une constante vraiment immuable, vous pouvez également la définir dans la classe du modèle:
class Card < ActiveRecord::Base COLOURS = ['white', 'blue'].freeze end # accessible as Card::COLOURS
Vous pouvez également créer des constantes globales accessibles partout dans l'initialiseur, comme dans l'exemple suivant. C'est probablement le meilleur endroit si vos couleurs sont vraiment globales et utilisées dans plusieurs contextes de modèles.
# put this into config/initializers/my_constants.rb COLOURS = ['white', 'blue'].freeze
Note: quand on définit les constantes ci-dessus, on veut souvent freeze
le tableau. Cela empêche les autres codes de modifier ultérieurement (par inadvertance) le tableau en ajoutant par exemple un nouvel élément. Une fois qu'un object est gelé, il ne peut plus être modifié.
Quelques options:
En utilisant une constante:
class Card COLOURS = ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze end
Lazy chargé à l’aide de la variable d’instance de classe:
class Card def self.colours @colours ||= ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze end end
Si c’est une constante vraiment globale ( évitez les constantes globales de cette nature, cependant ), vous pouvez également envisager de mettre une constante de niveau supérieur dans config/initializers/my_constants.rb
par exemple.
A partir de Rails 5.0, vous pouvez utiliser l’object de configuration
directement pour la configuration personnalisée :
Dans config/application.rb
(ou config/custom.rb
si vous préférez)
config.colours = %w(white blue black red green)
Il sera disponible comme:
Rails.configuration.colours # => ["white", "blue", "black", "red", "green"]
Remarque: Pour la version 4.2, vous devez utiliser la propriété config.x
:
config.x.colours = %w(white blue black red green)
Qui sera disponible comme:
Rails.configuration.x.colours # => ["white", "blue", "black", "red", "green"]
Si une constante est nécessaire dans plusieurs classes, je la place dans config / initializers / contant.rb toujours en majuscules (la liste des états ci-dessous est tronquée).
STATES = ['AK', 'AL', ... 'WI', 'WV', 'WY']
Ils sont disponibles dans l’application, sauf dans le code modèle en tant que tel:
<%= form.label :states, %> <%= form.select :states, STATES, {} %>
Pour utiliser la constante dans un modèle, utilisez attr_accessor pour rendre la constante disponible.
class Customer < ActiveRecord::Base attr_accessor :STATES validates :state, inclusion: {in: STATES, message: "-- choose a State from the drop down list."} end
Pour les parameters d’application et pour les constantes globales, il est recommandé d’utiliser Settingslogic . Ces parameters sont stockés dans un fichier YML et sont accessibles à partir de modèles, de vues et de contrôleurs. Encore plus .. vous pouvez créer différents parameters pour tous vos environnements:
# 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
Quelque part dans la vue (je préfère les méthodes d'aide pour ce genre de choses) ou dans un modèle, vous pouvez obtenir, par exemple, un tableau de couleurs Settings.colors.split(/\s/)
. C'est très flexible. Et vous n'avez pas besoin d'inventer un vélo.
Utilisez une méthode de classe:
def self.colours ['white', 'red', 'black'] end
Model.colours
renvoie alors ce tableau. Vous pouvez également créer un initialiseur et envelopper les constantes dans un module pour éviter les conflits d’espace de noms.
Un endroit commun pour placer des constantes globales à l’échelle de l’application se trouve dans config/application
.
module MyApp FOO ||= ENV.fetch('FOO', nil) BAR ||= %w(one two three) class Application < Rails::Application config.foo_bar = :baz end end
Une autre option, si vous souhaitez définir vos constantes en un seul endroit:
module DSL module Constants MY_CONSTANT = 1 end end
Mais toujours les rendre globalement visibles sans avoir à y accéder de manière entièrement qualifiée:
DSL::Constants::MY_CONSTANT # => 1 MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT Object.instance_eval { include DSL::Constants } MY_CONSTANT # => 1
J’ai généralement un modèle / table de consultation dans mon programme de rails et je l’utilise pour les constantes. Il est très utile que les constantes soient différentes selon les environnements. De plus, si vous envisagez de les étendre, par exemple si vous souhaitez append «jaune» à une date ultérieure, vous pouvez simplement append une nouvelle ligne à la table de recherche et en terminer avec celle-ci.
Si vous autorisez l’administrateur à modifier cette table, ils ne vous contacteront pas pour maintenance. 🙂 SEC.
Voici à quoi ressemble mon code de migration:
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
J'utilise seeds.rb pour le pré-remplir.
Lookup.find_or_create_by_group_key_and_lookup_key_and_lookup_value!(group_key: 'development_COLORS', lookup_key: 'color1', lookup_value: 'red');
La variable globale doit être déclarée dans le répertoire config/initializers
COLOURS = %w(white blue black red green)
Selon votre condition, vous pouvez également définir des variables d’environnement et les récupérer via ENV['some-var']
dans le code ruby, cette solution pourrait ne pas vous convenir, mais j’espère que cela pourrait aider les autres.
Exemple: vous pouvez créer différents fichiers .development_env
, .production_env
, .test_env
et les charger en fonction de vos environnements applicatifs, vérifiez cette gen dotenv-rails qui automatise cela pour votre.
Essayez de garder tous les constants à un seul endroit. Dans mon application, j’ai créé un dossier de constantes dans les initialiseurs comme suit:
et je garde généralement toutes les constantes dans ces fichiers.
Dans votre cas, vous pouvez créer un fichier dans le dossier des constantes sous le nom colors_constant.rb
colors_constant.rb
N’oubliez pas de redémarrer le serveur