99 votes

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

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

export admin_password = "secret"

Mais y a-t-il un moyen de le faire dans mon code source de rails quelque part ? Ma première tentative était quelque chose comme ceci dans environment/development.rb

ENV['admin_password'] = "secret"

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

1 votes

Notez que la commande bash doit être export admin_password="secret" pas export admin_password = "secret" .

148voto

user664833 Points 4597

Ne jamais coder en dur des informations sensibles (identifiants de compte, mots de passe, etc.) . Créez plutôt 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 du code source. Par exemple, en ce qui concerne Git (système de gestion du 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'

De même, ajoutez les lignes suivantes à /config/environment.rb entre le require et la 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, en faisant cela vous allez charger vos variables d'environnement avant environments/*.rb ce qui signifie que vous pourrez faire référence à vos variables à l'intérieur de ces fichiers (par ex. environments/production.rb ). C'est un grand avantage par rapport au fait de mettre votre fichier de variables d'environnement à l'intérieur de /config/initializers/ .

À l'intérieur de app_environment_variables.rb il n'y a pas besoin de distinguer les environnements dans la mesure où développement o production parce que vous ne livrerez jamais ce fichier dans votre système de gestion du code source. développement par défaut. Mais si vous avez besoin de définir quelque chose de spécial pour l'élément test (ou pour les occasions où vous testez production mode localement ), il suffit d'ajouter un bloc conditionnel en dessous de 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 utilisiez des logiciels comme Apache/Passenger ou rails server :

-bash> touch tmp/restart.txt

Dans votre code, faites référence 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 dans app_environment_variables.rb vous devez spécifier booléens y numéros como chaînes de caractères (par exemple ENV['SEND_MAIL'] = 'false' pas seulement false y ENV['TIMEOUT'] = '30' pas seulement 30 ), sinon vous obtiendrez les erreurs can't convert false into String y can't convert Fixnum into String respectivement.

Stockage et partage d'informations sensibles

Le dernier noeud à faire est : comment partager ces informations sensibles avec vos clients et/ou partenaires ? Pour assurer la continuité des activités (par exemple, si vous êtes frappé par une étoile filante, comment vos clients et/ou partenaires pourront-ils reprendre l'exploitation complète du site ? L'envoi de ces informations par e-mail ou par courrier électronique n'est pas sûr et mène au désordre. Le stockage dans des 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 détails comme les mots de passe serait idéale.

Comment définir les 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 environnements multiples 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

Foreman et .env

De nombreux développeurs utilisent Foreman (installé avec le Ceinture d'outils Heroku ) à exécuter leurs applications localement (plutôt que d'utiliser des logiciels comme Apache/Passenger ou rails server ). Foreman et Heroku utilisent Procfile pour déclarer quelles commandes sont exécutées par votre application La transition du développement local à Heroku est donc transparente à cet égard. J'utilise Foreman et Heroku dans chaque projet Rails, donc cette commodité est formidable. Mais voici le problème Foreman charge les variables d'environnement stockées dans /.env via dotenv mais malheureusement dotenv ne fait qu'analyser le fichier pour trouver key=value paires ces paires ne deviennent pas des variables immédiatement, donc vous ne pouvez pas faire référence à des variables déjà définies (pour garder les choses DRY), et vous ne pouvez pas non plus faire du "Ruby" là-dedans (comme indiqué ci-dessus avec les conditionnelles), ce que vous pouvez faire en /config/app_environment_variables.rb . Par exemple, en ce qui concerne le maintien de l'anonymat, je fais parfois ce genre de choses :

ENV['SUPPORT_EMAIL']='Company Support <support@company.com>'
ENV['MAILER_DEFAULT_FROM'] = ENV['SUPPORT_EMAIL']
ENV['MAILER_DEFAULT_TO']   = ENV['SUPPORT_EMAIL']

C'est pourquoi j'utilise Foreman pour exécuter mes applications localement, mais je n'utilise pas son système de gestion de la qualité. .env pour le chargement des variables d'environnement ; j'utilise plutôt Foreman en conjonction avec l'application /config/app_environment_variables.rb décrite ci-dessus.

3 votes

J'aime cette solution car je voulais être sûr que les paramètres sensibles (clés d'API, etc.) soient protégés de manière adéquate dans un keystore, plutôt qu'en texte clair et sans être intégrés au dépôt Git. Merci.

88voto

Brandon Tilley Points 49142

[Mise à jour]

Alors que la solution de la rubrique "ancienne réponse" fonctionne pour les problèmes généraux, cette section vise à répondre à votre question spécifique après clarification de votre commentaire.

Vous devriez être en mesure de 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 la suivante :

Créer un fichier config/application.yml avec un hachage des 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] ainsi que toutes vos autres données. (Notez que puisque l'initialisateur inclut ERB.new votre fichier YAML peut contenir des balises ERB).

2 votes

Eh bien, j'utilise Heroku et ils vous permettent de définir certaines variables ENV pour des choses comme les mots de passe que vous ne voulez pas vérifier dans le contrôle de la source. J'essaie de trouver la meilleure chose à faire sur ma machine de développement. Et oui, j'essaie d'utiliser les données dans mon application.

0 votes

Heureux de l'entendre ! Si vous pensez qu'une réponse est correcte, vous devez la marquer en cochant la case à côté de la question. Cela vous vaudra, à vous et à la personne qui a répondu, une réputation et aidera également les personnes qui trouveront cette question à l'avenir à trouver la bonne réponse.

0 votes

Oh oui, je suis un nouvel utilisateur donc il me fait attendre 19 heures avant de pouvoir le vérifier. Encore 3 heures à attendre :) Mais merci pour toute votre aide ! En fait, si vous pouviez modifier votre réponse en supprimant l'élément dev_environment.rb et le remplacer par le mien, je marquerai volontiers votre réponse qui est beaucoup plus complète.

13voto

Lan Points 188

La façon dont j'essaie de le faire dans ma question fonctionne en fait !

# environment/development.rb

ENV['admin_password'] = "secret" 

J'ai juste dû redémarrer le serveur. Je pensais que l'exécution reload! dans la console rails serait suffisant mais j'ai aussi dû redémarrer le serveur web.

Je choisis ma propre réponse parce que je pense que c'est un meilleur endroit pour mettre et définir les variables ENV.

0 votes

Content que tu aies trouvé pourquoi ça ne marchait pas ! Personnellement, j'aime sauvegarder config/application.rb y config/environments/*.rb pour la mise en place de la Rails et en utilisant d'autres méthodes pour mettre en place mon application mais cela ne signifie certainement pas que c'est la seule façon (ou même la "bonne" façon :)

0 votes

J'ai été un peu déstabilisé parce que j'essayais de régler les choses différemment entre la production et le développement. Mais maintenant, je suis tout à fait d'accord avec vous ! Merci d'avoir non seulement répondu à ma question initiale, mais aussi de m'avoir aidé à mieux comprendre la structure des applications Rails !

8voto

Aupajo Points 2387

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

Avec l'application Heroku Contremaître vous pouvez créer des variables d'environnement par projet dans un fichier de type .env fichier :

ADMIN_PASSOWRD="secret"

Con Pow vous pouvez utiliser un .powenv fichier :

export ADMIN_PASSOWRD="secret"

1voto

goncalossilva Points 1372

L'environnement du système et l'environnement des rails sont des choses différentes. ENV vous permet de travailler avec l'environnement des rails, mais si ce que vous voulez faire est de changer l'environnement du système en cours d'exécution, vous pouvez simplement entourer la commande avec des backticks.

# ruby code
`export admin_password="secret"`
# more ruby code

1 votes

Il faut savoir que export se plaindra des espaces ; essayez export admin_password="secret"

0 votes

J'ai oublié ce détail (très important). J'ai corrigé ma réponse, merci !

0 votes

Cela ne fonctionne pas car les backticks génèrent un sous-shell et les variables que vous définissez dans le sous-shell ne peuvent pas affecter l'environnement du parent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X