Ich fange gerade mit meiner ersten Ruby on Rails-Webanwendung an. Ich habe eine Reihe verschiedener Modelle, Ansichten, Controller und so weiter.
Ich möchte einen guten Ort finden, um Definitionen von wirklich globalen Konstanten festzuhalten, die für meine gesamte App gelten. Insbesondere gelten sie sowohl für die Logik meiner Modelle als auch für die Entscheidungen, die in meinen Ansichten getroffen wurden. Ich kann keinen trockenen Ort finden, an dem diese Definitionen sowohl für alle meine Modelle als auch für alle meine Ansichten verfügbar sind .
Um ein bestimmtes Beispiel zu nennen, möchte ich eine Konstante COLOURS = ['white', 'blue', 'black', 'red', 'green']
. Dies wird überall verwendet, sowohl in Modellen als auch in Ansichten. Wo kann ich es an nur einem Ort definieren, damit es zugänglich ist?
Was ich versucht habe:
- Konstante Klassenvariablen in der Datei model.rb, mit denen sie am meisten verknüpft sind, z
@@COLOURS = [...]
. Aber ich konnte keinen vernünftigen Weg finden, es so zu definieren, dass ich in meine Ansichten schreiben kann,Card.COLOURS
anstatt etwas Klobiges wieCard.first.COLOURS
. - Eine Methode am Modell, so etwas wie
def colours ['white',...] end
- das gleiche Problem. - Eine Methode in application_helper.rb - das mache ich bisher, aber auf die Helfer kann nur in Ansichten zugegriffen werden, nicht in Modellen
- Ich glaube, ich habe etwas in application.rb oder environment.rb ausprobiert, aber diese scheinen nicht wirklich richtig zu sein (und sie scheinen auch nicht zu funktionieren).
Gibt es einfach keine Möglichkeit, etwas zu definieren, auf das sowohl von Modellen als auch von Ansichten aus zugegriffen werden kann? Ich meine, ich weiß, dass Modelle und Ansichten getrennt sein sollten, aber in einigen Bereichen wird es sicherlich Zeiten geben, in denen sie auf dasselbe domänenspezifische Wissen verweisen müssen.
quelle
Antworten:
Wenn Ihr Modell wirklich für die Konstanten "verantwortlich" ist, sollten Sie sie dort anbringen. Sie können Klassenmethoden erstellen, um auf sie zuzugreifen, ohne eine neue Objektinstanz zu erstellen:
Alternativ können Sie Klassenvariablen und einen Accessor erstellen. Dies wird jedoch nicht empfohlen, da Klassenvariablen bei der Vererbung und in Multithread-Umgebungen möglicherweise überraschend wirken.
Mit den beiden oben genannten Optionen können Sie das zurückgegebene Array bei jedem Aufruf der Accessor-Methode bei Bedarf ändern. Wenn Sie eine wirklich unveränderliche Konstante haben, können Sie diese auch für die Modellklasse definieren:
Sie können auch globale Konstanten erstellen, auf die von überall in einem Initialisierer wie im folgenden Beispiel zugegriffen werden kann. Dies ist wahrscheinlich der beste Ort, wenn Ihre Farben wirklich global sind und in mehr als einem Modellkontext verwendet werden.
Hinweis: Wenn wir oben Konstanten definieren, möchten wir häufig
freeze
das Array. Dies verhindert, dass anderer Code das Array später (versehentlich) ändert, indem beispielsweise ein neues Element hinzugefügt wird. Sobald ein Objekt eingefroren ist, kann es nicht mehr geändert werden.quelle
config/initializers/my_constants.rb
Route gehen, denken Sie daran, den Server neu zu starten:touch tmp/restart.txt
def self.colours
Beispiel ist nicht ideal. Bei jedem Aufrufdef self.colours
wird eine neue Instanz des Arrays zurückgegeben .#freeze
wird in diesem Fall nicht helfen. Es wird empfohlen, es als Ruby-Konstante zu deklarieren. In diesem Fall erhalten Sie immer dasselbe Objekt zurück.class Card; COLOURS = ['white', 'blue'].freeze; def self.colours; COLOURS; end; end
Die Zuweisung eines Arrays in einer beliebigen Sprache kann jedoch möglicherweise problematisch sein. Zum einen wird Speicher ohne (guten) Grund verwendet. Wenn Sie aus einer Datenbank laden und den Wert zwischenspeichern möchten, können Sie auch eine Klasseninstanzvariable verwenden, die mithilfe derdef self.colours
Methode verzögert geladen werden kann. Einverstanden über den Aspekt der Unveränderlichkeit.Einige Optionen:
Verwenden einer Konstante:
Lazy geladen mit Klasseninstanzvariable:
Wenn es sich um eine wirklich globale Konstante handelt ( vermeiden Sie jedoch globale Konstanten dieser Art ), können Sie beispielsweise auch eine Konstante der obersten Ebene eingeben
config/initializers/my_constants.rb
.quelle
extend
das Modul in der Klasse, damit es mit verfügbar istCard.COLOURS
.extend
funktioniert es bei mir nicht. Bei der Verwendunginclude
kann ich wieCard::COLOURS
/models
. Es ist viel besser, wenn Sie einen Initialisierer erstellen./models
, aber nur, wenn es sich in einem Modul befindet, z. B.module Constants; COLOURS = ...; end
in einer aufgerufenen Dateimodels/constants.rb
.Ab Rails 4.2 können Sie die
config.x
Eigenschaft verwenden:Welches wird verfügbar sein als:
Eine andere Methode zum Laden der benutzerdefinierten Konfiguration:
In den Rails 5 und 6 können Sie das
configuration
Objekt zusätzlich direkt für die benutzerdefinierte Konfiguration verwendenconfig.x
. Es kann jedoch nur für nicht verschachtelte Konfigurationen verwendet werden:Es wird verfügbar sein als:
quelle
Rails.configuration.colours
liebsten (obwohl ich wünschte, es wäre nicht so lange)config
ist so gut wieconfiguration
. Wir könnten hoffen, irgendwann eine Abkürzung zu bekommen :)Wenn eine Konstante in mehr als einer Klasse benötigt wird, füge ich sie in config / initializers / contant.rb immer in Großbuchstaben ein (Liste der folgenden Zustände wird abgeschnitten).
Sie sind in der gesamten Anwendung verfügbar, außer im Modellcode als solcher:
Um die Konstante in einem Modell zu verwenden, verwenden Sie attr_accessor, um die Konstante verfügbar zu machen.
quelle
config/initializers/constants.rb
wäre wahrscheinlich eine bessere WahlFür anwendungsweite Einstellungen und für globale Konstanten empfehle ich die Verwendung von Settingslogic . Diese Einstellungen werden in einer YML-Datei gespeichert und können über Modelle, Ansichten und Controller aufgerufen werden. Darüber hinaus können Sie verschiedene Einstellungen für alle Ihre Umgebungen erstellen:
Irgendwo in der Ansicht (ich bevorzuge Hilfsmethoden für solche Dinge) oder in einem Modell kann man zum Beispiel eine Reihe von Farben erhalten
Settings.colors.split(/\s/)
. Es ist sehr flexibel. Und Sie müssen kein Fahrrad erfinden.quelle
Verwenden Sie eine Klassenmethode:
Dann
Model.colours
wird das Array zurückgegeben. Alternativ können Sie einen Initialisierer erstellen und die Konstanten in ein Modul einschließen, um Namespace-Konflikte zu vermeiden.quelle
Versuchen Sie, alle an einem Ort konstant zu halten. In meiner Anwendung habe ich einen Konstantenordner in den Initialisierern wie folgt erstellt:
und ich halte normalerweise alle konstant in diesen Dateien.
In Ihrem Fall können Sie eine Datei im Konstantenordner als erstellen
colors_constant.rb
colours_constant.rb
Vergessen Sie nicht, den Server neu zu starten
quelle
Eine weitere Option, wenn Sie Ihre Konstanten an einer Stelle definieren möchten:
Machen Sie sie dennoch global sichtbar, ohne dass Sie vollständig qualifiziert darauf zugreifen müssen:
quelle
Ein üblicher Ort, um anwendungsweite globale Konstanten zu setzen, ist darin
config/application
.quelle
Normalerweise habe ich ein Nachschlagemodell / eine Nachschlagetabelle in meinem Rails-Programm und verwende es für die Konstanten. Es ist sehr nützlich, wenn die Konstanten für verschiedene Umgebungen unterschiedlich sein sollen. Wenn Sie planen, sie zu erweitern, beispielsweise zu einem späteren Zeitpunkt "Gelb" hinzufügen möchten, können Sie der Nachschlagetabelle einfach eine neue Zeile hinzufügen und damit fertig sein.
Wenn Sie dem Administrator die Berechtigung zum Ändern dieser Tabelle erteilen, werden diese nicht zur Wartung an Sie weitergeleitet. :) TROCKEN.
So sieht mein Migrationscode aus:
Ich benutze seeds.rb, um es vorab zu füllen.
quelle
Die globale Variable sollte im
config/initializers
Verzeichnis deklariert werdenquelle
Abhängig von Ihrem Zustand können Sie auch einige Umgebungsvariablen definieren und über
ENV['some-var']
Ruby-Code abrufen. Diese Lösung passt möglicherweise nicht zu Ihnen, aber ich hoffe, sie kann anderen helfen.Beispiel: Sie verschiedene Dateien erstellen können
.development_env
,.production_env
,.test_env
und laden Sie es Ihre Anwendungsumgebungen nach, überprüfen Sie diese gen dotenv-Schienen , die diese für Ihre automatisieren.quelle