web-dev-qa-db-fra.com

Est-il possible de définir des variables ENV pour l'environnement de développement Rails dans mon code?)?

Je sais que je peux définir mes variables ENV dans bash via

export admin_password = "secret"

Mais existe-t-il un moyen de le faire dans mon Rails quelque part??). Ma première tentative ressemblait à ceci dans environment/development.rb

ENV['admin_password'] = "secret"

Mais ça n'a pas marché. Y a-t-il un moyen de faire cela?

77
Lan

[Mise à jour]

Bien que la solution sous "ancienne réponse" fonctionne pour les problèmes généraux, cette section répond à votre question après clarification de votre commentaire.

Vous devriez pouvoir définir les variables d’environnement exactement comme vous le spécifiez dans votre question. Par exemple, j'ai une application Heroku qui utilise l'authentification de base HTTP.

# 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

Donc, dans votre cas, vous utiliseriez

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

N'oubliez pas de redémarrer le serveur pour que la configuration soit rechargée!

[Ancienne réponse]

Pour une configuration à l'échelle de l'application, vous pouvez envisager une solution comme celle-ci:

Créer un fichier config/application.yml avec une liste d’options auxquelles vous voulez pouvoir accéder:

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

Maintenant, créez le fichier config/initializers/app_config.rb et comprennent les éléments suivants:

require 'yaml'

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

Maintenant, n’importe où dans votre application, vous pouvez accéder à APP_CONFIG[:admin_password], avec toutes vos autres données. (Notez que puisque l’initialiseur inclut ERB.new, votre fichier YAML peut contenir un balisage ERB.)

77
Michelle Tilley

Ne jamais coder en dur des informations sensibles (identifiants de compte, mots de passe, etc.) . Au lieu de cela, créez un fichier pour stocker ces informations sous forme de variables d'environnement (paires clé/valeur) et excluez ce fichier de votre système de gestion de code source. Par exemple, en termes de Git (système de gestion de code source), excluez ce fichier en l’ajoutant à. gitignore:

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

/config/app_environment_variables.rb

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

Ajoutez également les lignes suivantes à /config/environment.rb, entre la ligne require et le Application.initialize ligne:

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

C'est ça!

Comme le dit le commentaire ci-dessus, vous chargez ainsi vos variables d'environnement avant le environments/*.rb, ce qui signifie que vous pourrez faire référence à vos variables dans ces fichiers (par exemple, environments/production.rb). C’est un avantage considérable par rapport à l’insertion de votre fichier de variables d’environnement dans /config/initializers/.

À l'intérieur app_environment_variables.rb il n’est pas nécessaire de distinguer les environnements jusqu’à développement ou production car vous ne pourrez jamais valider ce fichier dans votre système de gestion de code source; le développement contexte par défaut. Mais si vous devez définir quelque chose de spécial pour l'environnement test (ou pour les occasions où vous testez production mode localement) , ajoutez juste un bloc conditionnel ci-dessous toutes les autres variables:

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

Chaque fois que vous mettez à jour app_environment_variables.rb, redémarrez le serveur d'applications. En supposant que vous utilisez les goûts de Apache/Passenger ou Rails server:

-bash> touch tmp/restart.txt

Dans votre code, reportez-vous aux variables d'environnement comme suit:

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

Notez que l'intérieur app_environment_variables.rb vous devez spécifier booleans et nombres comme chaînes (par exemple ENV['SEND_MAIL'] = 'false' _ pas seulement false, et ENV['TIMEOUT'] = '30' pas seulement 30), sinon vous obtiendrez les erreurs can't convert false into String et can't convert Fixnum into String, respectivement.

Stocker et partager des informations sensibles

Le dernier nœud à nouer est le suivant: Comment partager ces informations sensibles avec vos clients et/ou partenaires? Aux fins de la continuité des activités (lorsque vous êtes frappé par une étoile filante, comment clients et/ou partenaires reprennent-ils toutes les opérations du site?), vos clients et/ou partenaires doivent connaître toutes les informations d'identification requises par votre application. L'envoi de courriels/skypes n'est pas sécurisé et conduit au désarroi. Le stocker dans Google Docs partagés n'est pas mauvais (si tout le monde utilise https), mais une application dédiée au stockage et au partage de petits titres comme les mots de passe serait idéale.

Comment définir des variables d'environnement sur Heroku

Si vous avez un seul environnement sur Heroku:

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

Si vous avez plusieurs environnements sur Heroku:

-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

Contremaître et .env

De nombreux développeurs utilisent Foreman (installé avec le Heroku Toolbelt ) à exécutent leurs applications localement (au lieu d'utiliser Apache/Passenger ou Rails server). Foreman et Heroku utilisent Procfile pour déclarer les commandes exécutées par votre application , la transition du développement local vers Heroku est donc transparente. J'utilise Foreman et Heroku dans chaque Rails projet, cette commodité est donc excellente. Mais voici la chose .. Foreman charge les variables d'environnement stockées dans /.env via dotenv mais malheureusement dotenv n’analyse que le fichier pour key=value _ paires ; ces paires ne deviennent pas des variables sur-le-champ, vous ne pouvez donc pas vous référer à des variables déjà définies (pour garder les choses sèches), vous ne pouvez pas non plus faire "Ruby" (comme indiqué ci-dessus avec les conditions), ce que vous pouvez faire. faire à /config/app_environment_variables.rb. Par exemple, pour garder les choses DRY), je fais parfois des choses comme celle-ci:

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

J'utilise donc Foreman pour exécuter mes applications localement, mais je n'utilise pas son .env fichier pour le chargement des variables d’environnement; j'utilise plutôt Foreman en conjonction avec le /config/app_environment_variables.rb approche décrite ci-dessus.

124
user664833

La façon dont je tente de le faire dans ma question fonctionne réellement!

# environment/development.rb

ENV['admin_password'] = "secret" 

Je viens de redémarrer le serveur. Je pensais courir reload! in Rails serait suffisante mais je devais également redémarrer le serveur Web.

Je choisis ma propre réponse car j'estime qu'il s'agit d'un meilleur endroit pour définir et définir les variables ENV.

10
Lan

Outre les solutions proposées, il existe des alternatives plus propres si vous utilisez certains serveurs de développement.

Avec Heroku Foreman , vous pouvez créer des variables d'environnement par projet dans un .env fichier:

ADMIN_PASSOWRD="secret"

Avec Pow , vous pouvez utiliser un .powenv fichier:

export ADMIN_PASSOWRD="secret"
8
Aupajo

Je pense que le meilleur moyen est de les stocker dans un fichier yml, puis de charger ce fichier en utilisant cette commande dans le fichier intializer

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

vous pouvez facilement accéder aux variables de configuration liées à l'environnement.

Votre structure de valeur de clé de fichier Yml:

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

production:
  app_key: 'xyz'
  app_secret: 'ghq'
2

L'environnement système et l'environnement de Rails sont des choses différentes. ENV vous permet de travailler avec l'environnement de Rails, mais si vous voulez changer l'environnement du système au moment de l'exécution, vous pouvez simplement entourer la commande de backticks.

# Ruby code
`export admin_password="secret"`
# more Ruby code
1
goncalossilva

Script de chargement du fichier personnalisé .env: Ajoutez les lignes suivantes à /config/environment.rb, Entre la ligne require et la ligne Application.initialize:

# 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

Et config/local_environment.env (Vous voudrez qu'il .gitignore) Ressemble à ceci:

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

(Basé sur la solution de @ user664833)

1
Daniel Garmoshka