Ist es möglich, ENV-Variablen für die Rails-Entwicklungsumgebung in meinem Code festzulegen?

80

Ich weiß, dass ich meine ENV-Variablen in bash über setzen kann

export admin_password = "secret"

Aber gibt es eine Möglichkeit, dies irgendwo in meinem Rails-Quellcode zu tun? Mein erster Versuch war so etwas inenvironment/development.rb

ENV['admin_password'] = "secret"

Aber es hat nicht funktioniert. Gibt es eine Möglichkeit, dies zu tun?

Lan
quelle
Beachten Sie, dass der Befehl bash export admin_password="secret"nicht sein sollte export admin_password = "secret".
Jacob Lockard

Antworten:

79

[Aktualisieren]

Während die Lösung unter "alte Antwort" für allgemeine Probleme funktioniert, dient dieser Abschnitt dazu, Ihre spezifische Frage nach Klärung aus Ihrem Kommentar zu beantworten.

Sie sollten in der Lage sein, Umgebungsvariablen genau so festzulegen, wie Sie es in Ihrer Frage angegeben haben. Als Beispiel habe ich eine Heroku-App, die die HTTP-Basisauthentifizierung verwendet.

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :authenticate

  def authenticate
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
    end
  end
end

# config/initializers/dev_environment.rb
unless Rails.env.production?
  ENV['HTTP_USER'] = 'testuser'
  ENV['HTTP_PASS'] = 'testpass'
end

Also in deinem Fall würdest du verwenden

unless Rails.env.production?
  ENV['admin_password'] = "secret"
end

Vergessen Sie nicht, den Server neu zu starten, damit die Konfiguration neu geladen wird!

[Alte Antwort]

Für die App-weite Konfiguration können Sie eine Lösung wie die folgende in Betracht ziehen:

Erstellen Sie eine Datei config/application.ymlmit einem Hash von Optionen, auf die Sie zugreifen möchten:

admin_password: something_secret
allow_registration: true
facebook:
  app_id: application_id_here
  app_secret: application_secret_here
  api_key: api_key_here

Erstellen Sie nun die Datei config/initializers/app_config.rbund fügen Sie Folgendes hinzu:

require 'yaml'

yaml_data = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config', 'application.yml'))).result)
APP_CONFIG = HashWithIndifferentAccess.new(yaml_data)

Jetzt können Sie überall in Ihrer Anwendung APP_CONFIG[:admin_password]zusammen mit all Ihren anderen Daten darauf zugreifen . (Beachten Sie, dass ERB.newIhre YAML-Datei ERB-Markup enthalten kann , da der Initialisierer enthält .)

Michelle Tilley
quelle
2
Nun, ich verwende Heroku und sie ermöglichen es Ihnen, einige ENV-Variablen für Dinge wie Passwörter festzulegen, die nicht in die Quellcodeverwaltung eingecheckt werden sollen. Ich versuche herauszufinden, was auf meiner Entwicklungsmaschine am besten zu tun ist. Und ja, ich versuche, die Daten in meiner App zu verwenden.
Lan
Froh das zu hören! Wenn Sie der Meinung sind, dass eine Antwort richtig ist, sollten Sie sie markieren, indem Sie das Häkchen neben der Frage aktivieren. Es wird Ihnen und dem Antwortenden den Ruf einbringen und auch Menschen helfen, die diese Frage in Zukunft finden, die richtige Antwort zu finden.
Michelle Tilley
Oh ja, ich bin ein neuer Benutzer, daher muss ich 19 Stunden warten, bevor ich es überprüfen kann. Noch 3 Stunden :) Aber danke für all deine Hilfe! Wenn Sie Ihre Antwort bearbeiten würden, indem Sie den dev_environment.rbCode entfernen und durch meinen ersetzen, würde ich Ihre Antwort gerne markieren, was viel gründlicher ist.
Lan
Ich mag das, aber aus irgendeinem Grund (Rails 3 v 4?) konnte die app_config.rb nicht geladen werden. Ich habe den Code in config / environment.rb eingefügt und den gleichen Effekt erhalten. # Laden der Rails-Anwendung erfordert File.expand_path ('../ application', FILE ) erfordert 'yaml' yaml_data = YAML :: load (ERB.new (IO.read (File.join (Rails.root, 'config'), 'local_env.yml'))). result) APP_CONFIG = HashWithIndifferentAccess.new (yaml_data) # Initialisiere die Rails-Anwendung Rails3 :: Application.initialize!
Ben
Es tut mir leid, einen so alten Thread zu öffnen, aber wäre eine für die Entwicklungsumgebung spezifische Einstellung in der config/environments/development.rbDatei nicht sinnvoller ?
Jeffdill2
129

Codieren Sie niemals vertrauliche Informationen (Anmeldeinformationen, Passwörter usw.) fest . Erstellen Sie stattdessen eine Datei, um diese Informationen als Umgebungsvariablen (Schlüssel / Wert-Paare) zu speichern, und schließen Sie diese Datei von Ihrem Quellcode-Verwaltungssystem aus. Schließen Sie diese Datei beispielsweise in Bezug auf Git (Quellcodeverwaltungssystem) aus, indem Sie sie hinzufügen. Gitignore :

-bash> echo '/config/app_environment_variables.rb' >> .gitignore 

/config/app_environment_variables.rb

ENV['HTTP_USER'] = 'devuser'
ENV['HTTP_PASS'] = 'devpass'

Fügen Sie außerdem die folgenden Zeilen /config/environment.rbzwischen der requireZeile und der Application.initializeZeile hinzu:

# Load the app's custom environment variables here, so that they are loaded before environments/*.rb
app_environment_variables = File.join(Rails.root, 'config', 'app_environment_variables.rb')
load(app_environment_variables) if File.exists?(app_environment_variables)

Das ist es!

Wie der obige Kommentar sagt, laden Sie auf diese Weise Ihre Umgebungsvariablen zuvor environments/*.rb, was bedeutet, dass Sie auf Ihre Variablen in diesen Dateien verweisen können (z environments/production.rb. B. ). Dies ist ein großer Vorteil gegenüber dem Einfügen Ihrer Umgebungsvariablendatei /config/initializers/.

Im Inneren app_environment_variables.rbmüssen Umgebungen nicht in Bezug auf Entwicklung oder Produktion unterschieden werden, da Sie diese Datei niemals in Ihr Quellcode-Verwaltungssystem übertragen werden. Daher ist sie standardmäßig für den Entwicklungskontext vorgesehen . Aber wenn Sie für die zu Satz etwas Besonderes benötigen Testumgebung (oder für Gelegenheiten , bei denen Sie testen Produktionsmodus lokal ), fügen Sie einfach einen bedingten Block unter allen anderen Variablen:

if Rails.env.test?
  ENV['HTTP_USER'] = 'testuser'
  ENV['HTTP_PASS'] = 'testpass'
end

if Rails.env.production?
  ENV['HTTP_USER'] = 'produser'
  ENV['HTTP_PASS'] = 'prodpass'
end

Starten Sie app_environment_variables.rbden App-Server bei jedem Update neu. Angenommen, Sie verwenden Apache / Passenger oder rails server:

-bash> touch tmp/restart.txt

Verweisen Sie in Ihrem Code wie folgt auf die Umgebungsvariablen:

def authenticate
  authenticate_or_request_with_http_basic do |username, password|
    username == ENV['HTTP_USER'] && password == ENV['HTTP_PASS']
  end
end

Beachten Sie, dass app_environment_variables.rbSie im Inneren Boolesche Werte und Zahlen als Zeichenfolgen angeben müssen (z. B. ENV['SEND_MAIL'] = 'false'nicht nur falseund ENV['TIMEOUT'] = '30'nicht nur 30), da sonst die Fehler can't convert false into Stringbzw. angezeigt werdencan't convert Fixnum into String .

Speichern und Weitergeben vertraulicher Informationen

Der letzte Knoten ist: Wie können Sie diese vertraulichen Informationen mit Ihren Kunden und / oder Partnern teilen? Zum Zwecke der Geschäftskontinuität (dh wenn Sie von einem Sternschnuppen getroffen werden, wie werden Ihre Kunden und / oder Partner den vollen Betrieb der Website wieder aufnehmen?) Müssen Ihre Kunden und / oder Partner alle für Ihre App erforderlichen Anmeldeinformationen kennen . Das E-Mailen / Skyping dieser Dinge ist unsicher und führt zu Unordnung. Das Speichern in freigegebenen Google Text & Tabellen ist nicht schlecht (wenn jeder https verwendet), aber eine App zum Speichern und Freigeben kleiner Leckerbissen wie Kennwörter wäre ideal.

So legen Sie Umgebungsvariablen in Heroku fest

Wenn Sie eine einzige Umgebung auf Heroku haben:

-bash> heroku config:add HTTP_USER='herouser'
-bash> heroku config:add HTTP_USER='heropass'

Wenn Sie mehrere Umgebungen auf Heroku haben:

-bash> heroku config:add HTTP_USER='staguser' --remote staging
-bash> heroku config:add HTTP_PASS='stagpass' --remote staging

-bash> heroku config:add HTTP_USER='produser' --remote production
-bash> heroku config:add HTTP_PASS='prodpass' --remote production

Foreman und .env

Viele Entwickler verwenden Foreman (installiert mit dem Heroku Toolbelt ), um ihre Apps lokal auszuführen (im Gegensatz zu Apache / Passenger oder rails server). Foreman und Heroku geben Procfilean, welche Befehle von Ihrer Anwendung ausgeführt werden , sodass der Übergang vom lokalen Entwickler zu Heroku in dieser Hinsicht nahtlos verläuft. Ich verwende Foreman und Heroku in jedem Rails-Projekt, daher ist diese Bequemlichkeit großartig. Aber hier ist die Sache. Foreman lädt Umgebungsvariablen, die /.envüber dotenv gespeichert sind, aber leider analysiert dotenv die Datei im Wesentlichen nur für key=valuePaare;; Diese Paare werden nicht genau dort und dann zu Variablen, sodass Sie weder auf bereits festgelegte Variablen verweisen können (um die Dinge trocken zu halten), noch können Sie dort "Ruby" ausführen (wie oben mit den Bedingungen angegeben), was Sie können tun in /config/app_environment_variables.rb. Zum Beispiel mache ich manchmal solche Sachen, um die Dinge trocken zu halten:

ENV['SUPPORT_EMAIL']='Company Support <[email protected]>'
ENV['MAILER_DEFAULT_FROM'] = ENV['SUPPORT_EMAIL']
ENV['MAILER_DEFAULT_TO']   = ENV['SUPPORT_EMAIL']

Daher verwende ich Foreman, um meine Apps lokal auszuführen, aber ich verwende die .envDatei nicht zum Laden von Umgebungsvariablen. Vielmehr verwende ich Foreman in Verbindung mit dem /config/app_environment_variables.rboben beschriebenen Ansatz.

user664833
quelle
3
Ich mag diese Lösung, da ich sicherstellen wollte, dass vertrauliche Einstellungen (API-Schlüssel usw.) in einem Schlüsselspeicher angemessen geschützt sind, anstatt in Klartext und nicht mit dem Git-Repository gebündelt. Vielen Dank.
Rori Stumpf
10

Die Art und Weise, wie ich dies in meiner Frage versuche, funktioniert tatsächlich!

# environment/development.rb

ENV['admin_password'] = "secret" 

Ich musste nur den Server neu starten. Ich dachte, es reload!würde ausreichen, in der Rails-Konsole zu laufen , aber ich musste auch den Webserver neu starten.

Ich wähle meine eigene Antwort aus, weil ich der Meinung bin, dass dies ein besserer Ort ist, um die ENV-Variablen zu setzen und festzulegen

Lan
quelle
Ich bin froh, dass du herausgefunden hast, warum es nicht funktioniert hat! Ich persönlich mag es, die Rails- Umgebung zu speichern config/application.rbund config/environments/*.rbeinzurichten und andere Methoden zum Einrichten meiner Anwendungsumgebung zu verwenden, aber das bedeutet sicherlich nicht, dass dies der einzige (oder sogar der "richtige" Weg ist :)
Michelle Tilley
Ich wurde ein wenig abgeworfen, weil ich versuchte, die Dinge zwischen Produktion und Entwicklung anders einzustellen. Aber jetzt stimme ich Ihnen vollkommen zu! Vielen Dank, dass Sie nicht nur meine ursprüngliche Frage beantwortet haben, sondern mir auch geholfen haben, die Struktur der Rails-App besser zu verstehen!
Lan
8

Abgesehen von den hier aufgeführten Lösungen gibt es sauberere Alternativen, wenn Sie bestimmte Entwicklungsserver verwenden.

Mit Herokus Foreman können Sie projektbezogene Umgebungsvariablen in einer .envDatei erstellen:

ADMIN_PASSOWRD="secret"

Mit Pow können Sie eine .powenvDatei verwenden:

export ADMIN_PASSOWRD="secret"
Aupajo
quelle
2

Ich denke, der beste Weg ist, sie in einer yml-Datei zu speichern und diese Datei dann mit diesem Befehl in die Intializer-Datei zu laden

APP_CONFIG = YAML.load_file("#{Rails.root}/config/CONFIG.yml")[Rails.env].to_hash

Sie können problemlos auf umgebungsbezogene Konfigurationsvariablen zugreifen.

Ihre Yml-Dateischlüsselwertstruktur:

development:
  app_key: 'abc'
  app_secret: 'abc'

production:
  app_key: 'xyz'
  app_secret: 'ghq'
Taimoor Changaiz
quelle
1

Die Systemumgebung und die Schienenumgebung sind verschiedene Dinge. ENVLassen Sie uns mit der Rails-Umgebung arbeiten. Wenn Sie jedoch die Systemumgebung zur Laufzeit ändern möchten, können Sie den Befehl einfach mit Backticks umgeben.

# ruby code
`export admin_password="secret"`
# more ruby code
Goncalossilva
quelle
1
Nur eine Notiz, exportdie sich über die Räume beschweren wird; versuchen Sieexport admin_password="secret"
Michelle Tilley
Ich habe dieses (sehr wichtige) Detail vergessen. Meine Antwort wurde korrigiert, danke!
Goncalossilva
Dies funktioniert nicht, da Backticks eine Unterschale erzeugen und Variablen, die Sie in der Unterschale festlegen, die Umgebung des übergeordneten Elements nicht beeinflussen können.
AndrewF
Nein, es funktioniert. Die Antwort richtet sich, wie klar erläutert, nicht an die Umgebung des Elternteils. Es gibt sehr gute Antworten, die Anweisungen dazu geben.
Goncalossilva
1

Skript zum Laden einer benutzerdefinierten .envDatei: Fügen Sie die folgenden Zeilen /config/environment.rbzwischen der requireZeile und der Application.initializeZeile hinzu:

# Load the app's custom environment variables here, so that they are loaded before environments/*.rb

app_environment_variables = File.join(Rails.root, 'config', 'local_environment.env')
if File.exists?(app_environment_variables)
  lines = File.readlines(app_environment_variables)
  lines.each do |line|
    line.chomp!
    next if line.empty? or line[0] == '#'
    parts = line.partition '='
    raise "Wrong line: #{line} in #{app_environment_variables}" if parts.last.empty?
    ENV[parts.first] = parts.last
  end
end

Und config/local_environment.env(du wirst es wollen .gitignore) wird aussehen wie:

# This is ignored comment
DATABASE_URL=mysql2://user:[email protected]:3307/database
RACK_ENV=development

(Basierend auf der Lösung von @ user664833)

Daniel Garmoshka
quelle