Je commence tout juste 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 des définitions de constantes véritablement mondiales, qui s'appliquent à l'ensemble de mon application. En particulier, ils s'appliquent à la fois dans la logique de mes modèles et dans les décisions prises selon mes vues. Je ne trouve aucun endroit SEC pour mettre ces définitions là où elles sont disponibles à la fois pour tous mes modèles et aussi 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 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é:
- Variables de classe constantes dans le fichier model.rb auxquelles elles sont le plus associées, telles que
@@COLOURS = [...]
. Mais je ne pouvais pas trouver une manière saine de le définir afin que je puisse écrire dans mes vuesCard.COLOURS
plutôt que quelque chose de maladroitCard.first.COLOURS
. - Une méthode sur le modèle, quelque chose comme
def colours ['white',...] end
- même problème. - Une méthode dans application_helper.rb - c'est ce que je fais jusqu'à présent, mais les assistants ne sont accessibles que dans les vues, pas dans les modèles
- Je pense que j'ai peut-être essayé quelque chose dans application.rb ou environment.rb, mais ceux-ci ne semblent pas vraiment corrects (et ils ne semblent pas fonctionner non plus)
N'y a-t-il simplement aucun moyen de définir quoi que ce soit pour être 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 y aura sûrement des fois où ils devront se référer aux mêmes connaissances spécifiques au domaine?
Réponses:
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'objet:
Alternativement, vous pouvez créer des variables de classe et un accesseur. Ceci est cependant déconseillé car les variables de classe peuvent sembler surprenantes avec l'héritage et dans les environnements multi-thread.
Les deux options ci-dessus vous permettent de modifier le tableau renvoyé à chaque appel de la méthode d'accesseur si nécessaire. Si vous avez une vraie constante vraiment immuable, vous pouvez également la définir sur la classe de modèle:
Vous pouvez également créer des constantes globales accessibles de partout dans un initialiseur comme dans l'exemple suivant. C'est probablement le meilleur endroit si vos couleurs sont vraiment globales et utilisées dans plus d'un contexte de modèle.
Remarque: lorsque nous définissons des constantes ci-dessus, nous voulons souvent
freeze
le tableau. Cela empêche un autre code de modifier ultérieurement (par inadvertance) le tableau en ajoutant par exemple un nouvel élément. Une fois qu'un objet est gelé, il ne peut plus être modifié.la source
config/initializers/my_constants.rb
voustouch tmp/restart.txt
def self.colours
exemple n'est pas idéal. Chaque fois que vous appelezdef self.colours
, une nouvelle instance du tableau sera retournée .#freeze
n'aidera pas dans ce cas. La meilleure pratique consiste à le déclarer en tant que constante Ruby, auquel cas vous récupérerez toujours le même objet.class Card; COLOURS = ['white', 'blue'].freeze; def self.colours; COLOURS; end; end
Cela dit, l'allocation d'un tableau dans n'importe quelle langue peut être potentiellement problématique; d'une part, il utilise la mémoire sans (bonne) raison. Si vous chargez à partir d'une base de données et que vous souhaitez mettre en cache la valeur, vous pouvez également utiliser une variable d'instance de classe, qui peut être chargée paresseusement à l'aide de ladef self.colours
méthode. Je suis d'accord sur l'aspect immuabilité.Quelques options:
En utilisant une constante:
Lazy chargé à l'aide de la variable d'instance de classe:
S'il s'agit d'une constante véritablement globale ( évitez cependant les constantes globales de cette nature ), vous pouvez également envisager de mettre une constante de niveau supérieur
config/initializers/my_constants.rb
par exemple.la source
extend
le module dans la classe pour qu'il soit disponible avecCard.COLOURS
.extend
son ne fonctionne pas pour moi. Lors de l'utilisation,include
je peux accéder comme:Card::COLOURS
/models
. C'est beaucoup mieux si vous créez un initialiseur./models
, mais seulement si c'est dans un module, par exemplemodule Constants; COLOURS = ...; end
dans un fichier appelémodels/constants.rb
.Depuis Rails 4.2, vous pouvez utiliser la
config.x
propriété:Qui sera disponible en tant que:
Une autre méthode de chargement de la configuration personnalisée:
Dans Rails 5 et 6 , vous pouvez utiliser l'
configuration
objet directement pour une configuration personnalisée, en plus deconfig.x
. Cependant, il ne peut être utilisé que pour une configuration non imbriquée:Il sera disponible sous la forme:
la source
Rails.configuration.colours
mieux (même si je souhaite que ce ne soit pas si long)config
c'est aussi bon queconfiguration
. Nous pourrions espérer obtenir un raccourci à un moment donné :)ApplicationController
s'il n'y a rien d'autre entre les deux. Si la constante n'est pas directement liée aux contrôleurs, je considérerais quand même une configuration globale, etc.Si une constante est nécessaire dans plus d'une classe, je la mets dans config / initializers / contant.rb toujours en majuscules (la liste des états ci-dessous est tronquée).
Ils sont disponibles dans toute l'application, sauf dans le code modèle en tant que tel:
Pour utiliser la constante dans un modèle, utilisez attr_accessor pour rendre la constante disponible.
la source
config/initializers/constants.rb
serait probablement un meilleur choixPour les paramètres à l'échelle de l'application et pour les constantes globales, je recommande d'utiliser Settingslogic . Ces paramètres sont stockés dans un fichier YML et sont accessibles à partir de modèles, de vues et de contrôleurs. De plus, vous pouvez créer différents paramètres pour tous vos environnements:
Quelque part dans la vue (je préfère les méthodes d'assistance 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.la source
Utilisez une méthode de classe:
Ensuite
Model.colours
retournera ce tableau. Vous pouvez également créer un initialiseur et encapsuler les constantes dans un module pour éviter les conflits d'espace de noms.la source
Essayez de garder tous les constants à un seul endroit, dans mon application, j'ai créé un dossier de constantes à l'intérieur des initialiseurs comme suit:
et je garde généralement tout constant dans ces fichiers.
Dans votre cas, vous pouvez créer un fichier sous le dossier des constantes comme
colors_constant.rb
colours_constant.rb
N'oubliez pas de redémarrer le serveur
la source
Une autre option, si vous souhaitez définir vos constantes en un seul endroit:
Mais toujours les rendre visibles à l'échelle mondiale sans avoir à y accéder de manière entièrement qualifiée:
la source
Un endroit commun pour mettre des constantes globales à l'échelle de l'application est à l'intérieur
config/application
.la source
J'ai généralement un modèle / table de «recherche» dans mon programme de rails et je l'utilise pour les constantes. C'est très utile si les constantes vont être différentes pour différents environnements. En outre, si vous avez l'intention de les étendre, par exemple si vous souhaitez ajouter «jaune» à une date ultérieure, vous pouvez simplement ajouter une nouvelle ligne à la table de recherche et en finir avec elle.
Si vous accordez aux administrateurs les autorisations pour modifier ce tableau, ils ne vous seront pas envoyés pour la maintenance. :) SEC.
Voici à quoi ressemble mon code de migration:
J'utilise seeds.rb pour le préremplir.
la source
La variable globale doit être déclarée dans le
config/initializers
répertoirela source
Selon votre état, vous pouvez également définir certaines variables environnementales et les récupérer via
ENV['some-var']
du code rubis, cette solution peut ne pas vous convenir, mais j'espère que cela peut aider les autres.Exemple: vous pouvez créer des fichiers différents
.development_env
,.production_env
,.test_env
et le charger selon vos environnements d'application, vérifiez ce gen dotenv rails qui automatisent ce pour votre.la source