本地和Heroku的环境变量

14

我有一个Sinatra应用程序,其中有一个yml文件用于设置环境变量,我使用这种方法调用它们:

module MyConfig

 def config
  environment = ENV["RACK_ENV"] || "development"
  YAML.load_file("./config/config.yml")[environment]
 end
 end

所以当我想要使用一个变量时,我会像这样做举例

aws_access_key_id = config['aws_access_key']

我有一个.gitignore文件,例如在将代码推送到GitHub时忽略了config.yml。那么当我推送到Heroku时,这些环境变量将无法访问?

因此,这使我只能使用Heroku的方式来设置它们,如下所示:

heroku config:add aws_access_key= myapikey

但是 Heroku 访问这些的方式如下:

aws_access_key_id = ENV['aws_access_key']

我应该如何设置我的开发环境以使用方法配置,而Heroku使用ENV?我是否从错误的角度看待了这个问题?或者我的配置方法已经为我完成了这个任务?

感谢任何帮助。

RAKEFILE

  require 'active_support/core_ext'
  require './config/config.rb'
  require 'bundler/setup'
  Bundler.require(:default)

   include MyConfig

  AssetSync.configure do |con|
  con.fog_provider = 'AWS'
  con.fog_region = 'eu-west-1'
  con.fog_directory = config['fog_directory']
  con.aws_access_key_id = config['aws_access_key']
  con.aws_secret_access_key = config['aws_secret_key']
  con.prefix = "assets"
  con.public_path = Pathname("./public")
  end

 namespace :assets do
 desc "Precompile assets"
 task :precompile do
  AssetSync.sync
 end
end
4个回答

19

更新:

我现在使用 dotenv gem 代替下面的示例。所以现在不再忽略 env.rb 文件,而是使用 Git 忽略 .env 文件。

原始帖子:

尝试这个,

# /env.rb

ENV['aws_bucket'] = 'my_bucket'
ENV['aws_access_key'] = 'my_access_key'
ENV['aws_access_secret'] = 'my_access_secret'

这个文件设置的ENV值与heroku config相同。

# /config.rb

require './env' if File.exists?('env.rb')

env.rb 只有在存在时才会被引入。

# /.gitignore

/env.rb

env.rb文件已被添加到.gitignore文件中,因此不会保存在Git中。

然后您将使用ENV ['key']而不是config ['key']来访问值。

如果env.rb不在与config.rb文件相同的目录中,您可能需要更改其路径。

编辑:

从之前的问题中查看您的Rakefile,您需要将其更改为以下内容:

# Rakefile

require 'bundler/setup'
Bundler.require(:default)
require './env' if File.exists?('env.rb')

AssetSync.configure do |con|
 con.fog_provider = 'AWS'
 con.fog_region = 'eu-west-1'
 con.fog_directory = ENV['aws_bucket']
 con.aws_access_key_id = ENV['aws_access_key']
 con.aws_secret_access_key = ENV['aws_access_secret']
 con.prefix = "assets"
 con.public_path = Pathname("./public")
end

namespace :assets do
  desc "Precompile assets"
  task :precompile do
    AssetSync.sync
  end
end

我假设在/config/config.rb中唯一的方法是config方法,因此我删除了逗号(,)。

require './config/config.rb'
include MyConfig

已经将config[key]替换为在env.rb中定义的ENV[key]值。您可能需要更改key名称以匹配。


再次感谢您的帮助,Sam。这一次在运行heroku run rake assets:precompile后,我遇到了“没有这样的文件或目录 - /config/config.yml”的问题,我理解这是因为它在.gitignore文件中?有什么想法可以解决这个问题吗? - Richlewis
尝试移除 YAML.load_file("./config/config.yml")[environment]。由于您已经用 env.rb 文件替换了 YAML 文件,因此不再需要包含它。 - Sam
非常感谢,如果我不打算使用Heroku,我可以继续使用config.yml的方式,但是您的方法同样适用,即使我没有使用Heroku。 - Richlewis
我甚至看不到它被定义了。 - Richlewis
谢谢Sam,但我需要Pony gem来处理我的邮件程序。我会尝试一下看看消息是否确实消失了,但之后呢? - Richlewis
显示剩余18条评论

1
我做的事情与Sam的建议类似,但有些不同。我也有一个YAML配置文件,但是我将其读取封装在一个Rake任务中,然后运行应用程序。
# in the Rakefile

require 'yaml'

def set_connstring
  s = %Q!postgres://#{ENV["DB_APP"]}@localhost/#{ENV["DB_APP"]}!
  ENV['DATABASE_URL'] ||= ENV["RACK_ENV"] == "test" ? "#{s}.test" : s
end


def basic_environment
  warn "  Setting up environment..."

  file = File.expand_path( File.join File.dirname(__FILE__), "./config.yml" )
  if File.exist? file
    YAML.load_file(file).each do |k,v|
      warn "-> #{k}"
      ENV[k.upcase] = v
    end
  end

  set_connstring()
end

namespace :app do

  desc "Set up the environment locally"
  task :environment do
    basic_environment()
  end

  desc "Run the app locally"
  task :run_local => "app:environment" do
    exec "bin/rackup config.ru -p #{ENV['RUN_LOCAL_PORT']}"
  end
end

这意味着我可以在本地运行它,而无需应用程序内部的任何代码来处理此问题。

编辑:顺便提一下,我注意到你在Rakefile中使用了Bundler.require(:default)。如果你使用bundle install --binstubs,那么Bundler会将所有可执行文件安装到项目中名为“bin/”的目录中。然后,如果你运行这些可执行文件,它们会自动使用Bundler安装的库,无需通过Bundler进行require。请参见http://gembundler.com/v1.2/man/bundle-exec.1.html


1

0

从Heroku管理界面直接导出:

设置->显示配置变量

然后打开浏览器JS控制台,粘贴以下内容并按回车键...

k=[];
$(".config-var-list input").map(function(y, x){k.push($(x).val())});
v=[];
$(".config-var-list textarea").map(function(y, x){v.push($(x).val())});
ret="";
k.map(function(x, i){ret+=k[i]+"\t"+v[2*i]+"\n"});
console.info(ret);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接