[ruby-on-rails] 내 코드에서 레일스 개발 환경에 대한 ENV 변수를 설정할 수 있습니까?

bash에서 내 ENV 변수를 다음을 통해 설정할 수 있음을 알고 있습니다.

export admin_password = "secret"

그러나 내 레일 소스 코드에서 어딘가에 할 수있는 방법이 있습니까? 내 첫 번째 시도는environment/development.rb

ENV['admin_password'] = "secret"

하지만 작동하지 않았습니다. 이를 수행하는 방법이 있습니까?



답변

[최신 정보]

“이전 답변”아래의 해결책이 일반적인 문제에 적용되지만이 섹션은 귀하의 의견을 명확히 한 후 특정 질문에 답변하는 것입니다.

질문에 지정한 것과 똑같이 환경 변수를 설정할 수 있어야합니다. 예를 들어 HTTP 기본 인증을 사용하는 Heroku 앱이 있습니다.

# 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

따라서 귀하의 경우에는

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

구성이 다시로드되도록 서버를 다시 시작하는 것을 잊지 마십시오!

[이전 답변]

앱 전체 구성의 경우 다음과 같은 솔루션을 고려할 수 있습니다.

config/application.yml액세스 할 수있는 옵션 해시로 파일 을 만듭니다 .

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

이제 파일을 만들고 config/initializers/app_config.rb다음을 포함합니다.

require 'yaml'

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

이제 애플리케이션의 어느 곳에서나 APP_CONFIG[:admin_password]다른 모든 데이터와 함께에 액세스 할 수 있습니다 . (이니셜 라이저에를 포함하므로 ERB.newYAML 파일에 ERB 마크 업이 포함될 수 있습니다.)


답변

민감한 정보 (계정 자격 증명, 암호 등)를 하드 코딩하지 마십시오 . 대신 해당 정보를 환경 변수 (키 / 값 쌍)로 저장하는 파일을 만들고 해당 파일을 소스 코드 관리 시스템에서 제외합니다. 예를 들어 Git (소스 코드 관리 시스템)의 경우. gitignore :

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

/config/app_environment_variables.rb

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

뿐만 아니라, 다음 줄을 추가 /config/environment.rb사이, require라인 및 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', 'app_environment_variables.rb')
load(app_environment_variables) if File.exists?(app_environment_variables)

그게 다야!

위의 주석에서 말했듯이 이렇게하면 이전에 환경 변수를로드하게됩니다. environments/*.rb즉, 해당 파일 (예 🙂 내에서 변수를 참조 할 수 있습니다 environments/production.rb. 이것은 환경 변수 파일을 내부에 넣는 것보다 큰 이점 /config/initializers/입니다.

내부 app_environment_variables.rb에서는 이 파일을 소스 코드 관리 시스템에 커밋하지 않기 때문에 개발 또는 프로덕션에 관한 환경을 구분할 필요 가 없으므로 기본적으로 개발 컨텍스트 용 입니다. 그러나 테스트 환경 (또는 로컬에서 프로덕션 모드 를 테스트하는 경우)에 대해 특별한 것을 설정해야하는 경우 다른 모든 변수 아래에 조건 블록을 추가하기 만하면 됩니다 .

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

을 업데이트 할 때마다 app_environment_variables.rb앱 서버를 다시 시작하십시오. Apache / Passenger 또는 rails server다음 과 같은 것을 사용한다고 가정합니다 .

-bash> touch tmp/restart.txt

코드에서 다음과 같이 환경 변수를 참조하십시오.

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

내부에 있습니다 app_environment_variables.rb지정해야 논리 값숫자 와 같은 문자열을 (예를 들어 ENV['SEND_MAIL'] = 'false'단지 falseENV['TIMEOUT'] = '30'단지 30) 그렇지 않으면 오류를 얻을 것이다 can't convert false into Stringcan't convert Fixnum into String각각.

민감한 정보 저장 및 공유

마지막 매듭 점은 이 민감한 정보를 고객 및 / 또는 파트너와 공유하는 방법 입니다. 비즈니스 연속성을 위해 (즉, 낙하하는 별에 맞을 때 고객 및 / 또는 파트너가 사이트의 전체 운영을 어떻게 재개합니까?), 고객 및 / 또는 파트너는 앱에 필요한 모든 자격 증명을 알아야합니다. . 이러한 것들을 이메일로 전송 / 스카이 핑하는 것은 안전하지 않으며 혼란을 초래합니다. 공유 된 Google 문서에 저장하는 것은 나쁘지 않지만 (모든 사람이 https를 사용하는 경우) 암호와 같은 작은 정보를 저장하고 공유하는 전용 앱이 이상적입니다.

Heroku에서 환경 변수를 설정하는 방법

Heroku에 단일 환경이있는 경우 :

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

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 및 .env

많은 개발자가 Foreman ( Heroku Toolbelt 와 함께 설치됨 ) 을 사용하여 앱을 로컬 에서 실행합니다 (Apache / Passenger 또는 같은 것을 사용하는 것과 반대 rails server). Foreman과 Heroku Procfile는 애플리케이션 에서 실행되는 명령을 선언하는 데 사용 하므로 로컬 개발에서 Heroku 로의 전환은 이와 관련하여 원활합니다. 저는 모든 Rails 프로젝트에서 Foreman과 Heroku를 사용하므로이 편리함이 좋습니다. 하지만 여기에 문제가 있습니다. Foreman /.env은 dotenv 를 통해 저장된 환경 변수를로드 하지만 불행히도 dotenv는 본질적으로 key=value쌍에 대한 파일 만 구문 분석합니다.; 이러한 쌍은 바로 거기에서 변수가되지 않으므로 이미 설정된 변수를 참조 할 수 없으며 (DRY를 유지하기 위해) 거기에서 “Ruby”를 수행 할 수 없습니다 (위의 조건문에서 언급했듯이). 에서 수행하십시오 /config/app_environment_variables.rb. 예를 들어, DRY를 유지하는 측면에서 때때로 다음과 같은 작업을 수행합니다.

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

따라서 저는 Foreman을 사용하여 로컬에서 앱을 실행하지만 .env환경 변수를로드 하는 데 파일을 사용하지 않습니다 . 오히려 /config/app_environment_variables.rb위에서 설명한 접근 방식 과 함께 Foreman을 사용 합니다.


답변

내 질문에서 이것을 시도하는 방식이 실제로 작동합니다!

# environment/development.rb

ENV['admin_password'] = "secret"

서버를 다시 시작해야했습니다. reload!Rails 콘솔에서 실행하는 것으로 충분 하다고 생각 했지만 웹 서버도 다시 시작해야했습니다.

ENV 변수를 넣고 설정하는 것이 더 좋은 곳이라고 생각하기 때문에 내 대답을 선택하고 있습니다.


답변

여기 솔루션 외에도 특정 개발 서버를 사용하는 경우 더 깨끗한 대안이 있습니다.

Heroku의 Foreman을 사용하면 .env파일 에 프로젝트 별 환경 변수를 만들 수 있습니다 .

ADMIN_PASSOWRD="secret"

함께 , 당신은 사용할 수있는 .powenv파일 :

export ADMIN_PASSOWRD="secret"


답변

가장 좋은 방법은 yml 파일에 저장 한 다음 intializer 파일에서이 명령을 사용하여 해당 파일을로드하는 것입니다.

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

환경 관련 구성 변수에 쉽게 액세스 할 수 있습니다.

Yml 파일 키 값 구조 :

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

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


답변

시스템 환경과 레일의 환경은 다릅니다. ENVRails의 환경으로 작업 해 보겠습니다.하지만 런타임에 시스템 환경을 변경하려는 경우 명령을 백틱으로 묶을 수 있습니다.

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


답변

스크립트 사용자 정의의 로딩을위한 .env파일을 다음 줄을 추가 /config/environment.rb사이, require라인 및 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

그리고 config/local_environment.env(원할 .gitignore것입니다) 다음과 같이 보일 것입니다.

# This is ignored comment
DATABASE_URL=mysql2://user:psw@0.0.0:3307/database
RACK_ENV=development

(@ user664833 솔루션 기반)