Environment variables locally and Heroku
Solution 1
Update:
I now use the dotenv gem instead of the example below. So instead of ignoring the env.rb
file, I now ignore the .env
file with Git.
Original post:
Try this,
# /env.rb
ENV['aws_bucket'] = 'my_bucket'
ENV['aws_access_key'] = 'my_access_key'
ENV['aws_access_secret'] = 'my_access_secret'
This file sets the same ENV
values as heroku config
would do.
# /config.rb
require './env' if File.exists?('env.rb')
The env.rb
will only get required if it exists.
# /.gitignore
/env.rb
The env.rb
has been added to the .gitignore
file so it isn't kept in Git.
You would then access the values using ENV['key']
instead of config['key']
.
You might need to change the path to the env.rb
if it's not in the same directory as the config.rb
file.
EDIT:
From looking at your Rakefile
in the previous question, you need to change it to this:
# 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
I've assumed that the only method in /config/config.rb
was the config
method so I've removed the,
require './config/config.rb'
include MyConfig
And swapped the config[key]
for the ENV[key]
values defined in env.rb
. You may need to change the key
names to match up.
Solution 2
I do something similar to Sam's suggestion, but a little bit different. I have a YAML config file too, but I wrap the reading of it in a Rake task, which then runs the app.
# 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
It means I can run it locally without any code inside the app to deal with this.
Edit: a quick aside, I notice you have Bundler.require(:default)
in your Rakefile. If you use bundle install --binstubs
then Bundler installs all executables into a dir named "bin/" within the project. Then, if you run any of those executables they automatically use the libraries installed by Bundler, no need to require via Bundler. See http://gembundler.com/v1.2/man/bundle-exec.1.html.
Solution 3
You could delete the yaml, and describe the environment variables in a .env
file then start your app with foreman start
. See https://devcenter.heroku.com/articles/config-vars#local-setup
Or keep your hybrid system, where you load a yaml in dev, and use environment variables on heroku.
Related videos on Youtube
Richlewis
Software Tester Ruby Ruby On Rails HTML CSS Javascript jQuery Follow me on twitter @richl14
Updated on June 21, 2022Comments
-
Richlewis about 2 years
I have a sinatra app in which i have a yml file to set environment variables, i call them using this method
module MyConfig def config environment = ENV["RACK_ENV"] || "development" YAML.load_file("./config/config.yml")[environment] end end
so when i want to use a variable i do this for example
aws_access_key_id = config['aws_access_key']
I have a .gitignore file that ignores config.yml when pushing to github for example.So when I push to heroku these environment variables will not be accessible?
So this leaves me with using the heroku way of setting them like so
heroku config:add aws_access_key= myapikey
but heroku accesses these like
aws_access_key_id = ENV['aws_access_key']
How can i set my dev environment to use method config and heroku use ENV, am i looking at this the wrong way? or does my config method do this for me?
Any help appreciated
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
-
Richlewis over 11 yearsThanks again for your help Sam, this time after running heroku run rake assets:precompile I get No such file or directory - /config/config.yml, which i understand as it is in the .gitignore file? any ideas how to get around this?
-
Sam over 11 yearsTry removing
YAML.load_file("./config/config.yml")[environment]
. Since you have replaced the YAML file with theenv.rb
file, you no longer need to include it. -
Richlewis over 11 yearsyes i tried that but then i get undefined method or local variable config, as my rake file calls the method, ive posted the rakefile
-
Sam over 11 yearsYou will have to move all your YAML
config[key]
properties intoenv.rb
and change them toENV[key]
properties. Then remove all references to theconfig[key]
method inMyConfig
. -
Richlewis over 11 yearsthanks very much, so if i wasnt going to use heroku i could stick with the config.yml way, but then again your method works just aswell even if i didnt use heroku
-
Sam over 11 yearsYes, I think the YAML way is cleaner if you can symlink on the server. Heroku uses ENV for it's config and doesn't allow symlinking, so the
env.rb
is more suitable here. -
Richlewis over 11 yearsalmost there, error now warning: already initialized constant VALID_CHARACTER, after some reading i cant see anything wrong with my variables, im assuming there is no issue with ENV?
-
Sam over 11 yearsHave you defined
VALID_CHARACTER
twice maybe? Possibly in different files? That error means the ruby constant namedVALID_CHARACTER
has been defined more than once. A ruby constant should only be defined once and shouldn't change. -
Richlewis over 11 yearsi cant even see it defined Once
-
Sam over 11 yearsTry dropping the lines,
require 'active_support/core_ext'
andrequire 'asset_sync'
. The Gemfile should be requiring these already. Answer updated. -
Richlewis over 11 yearsstill get warning: already initialized constant VALID_CHARACTER, fog_directory cant be blank
-
Sam over 11 yearsDoes your
ENV[]
key in therakefile
match the key in theenv.rb
file for the bucket? -
Richlewis over 11 yearsENV['aws_bucket'] = 'applecatering' (env) and con.fog_directory = ENV['aws_bucket'] (rakefile)
-
Richlewis over 11 yearsi have my env.rb file in this structure config/env.rb so this is correct ye? require './env' if File.exists?('env.rb')
-
Sam over 11 yearsAh! Add
require './config/env' if File.exists?('config/env.rb')
to theRakefile
. It was removed whenconfig.rb
was removed. -
Sam over 11 yearsI'm out of ideas for now. Might have to come back to this later.
VALID_CHARACTER
is a contant in ActiveSupport and I think it's being defined twice but I'm not sure why. -
Richlewis over 11 yearsok so in my gemfile i have gem 'activesupport', require: 'active_support', activesupport comes as default doesnt it?
-
Richlewis over 11 yearsi have uninstalled gem activesupport and then re run bundle without this in the gemfile, still same problem
-
Sam over 11 yearsI would suggest ignoring the warning message. AssetSync has
activesupport
in it's gemspec so that's getting included any way. It seems to be conflicting with the constant defined in themail
gem from thepony
gemspec. If you remove the 'pony' gem, the warning will stop. Are there any other error messages after thepony
gem is removed? -
Richlewis over 11 yearsthanks sam, but i need the pony gem for my mailer, ill try it just to see if message does infact go away but what then?
-
Richlewis over 11 yearsrake command for heroku doesnt compile anything? just starts the rake and then goes back to terminal ready for new command
-
Richlewis over 11 yearsactually just checked my aws account and last update was yesterday, not the rake task i just completed
-
Sylar over 5 yearsThank you! In my case, Heroku uses the config.ru (.ru ext)