1

So I'm writing a Facebook App using Rails, and hosted on Heroku.

On Heroku, you deploy by pushing your repo to the server.

When I do this, I'd like it to automatically change a few dev settings (facebook secret, for example) to production settings.

What's the best way to do this? Git hook?

andrewheins
  • 788
  • 2
  • 9
  • 17

2 Answers2

4

There are a couple of common practices to handle this situation if you don't want to use Git hooks or other methods to modify the actual code upon deploy.

Environment Based Configuration

If you don't mind having the production values your configuration settings in your repository, you can make them environment based. I sometimes use something like this:

# config/application.yml

default:
  facebook:
    app_id: app_id_for_dev_and_test
    app_secret: app_secret_for_dev_and_test
    api_key: api_key_for_dev_and_test

production:
  facebook:
    app_id: app_id_for_production
    app_secret: app_secret_for_production
    api_key: api_key_for_production

# config/initializers/app_config.rb

require 'yaml'

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

config = yaml_data["default"]
begin
  config.merge! yaml_data[Rails.env]
rescue TypeError
  # nothing specified for this environment; do nothing
end

APP_CONFIG = HashWithIndifferentAccess.new(config)

Now you can access the data via, for instance, APP_CONFIG[:facebook][:app_id], and the value will automatically be different based on which environment the application was booted in.

Environment Variables Based Configuration

Another option is to specify production data via environment variables. Heroku allows you to do this via config vars.

  1. Set up your code to use a value based on the environment (maybe with optional defaults):

    facebook_app_id = ENV['FB_APP_ID'] || 'some default value'
    
  2. Create the production config var on Heroku by typing on a console:

    heroku config:add FB_APP_ID=the_fb_app_id_to_use
    

Now ENV['FB_APP_ID'] is the_fb_app_id_to_use on production (Heroku), and 'some default value' in development and test.

The Heroku documentation linked above has some more detailed information on this strategy.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • For now, this is the solution that I've gone with. It works great. Thank-you. Also, the description of HashWithIndifferentAccess is hilarious, if you haven't seen it: http://as.rubyonrails.org/classes/HashWithIndifferentAccess.html – andrewheins Jan 28 '12 at 20:04
0

You can explore the idea of a content filter, based on a 'smudge' script executed automatically on checkout.

content filter

You would declare:

  • some (versioned) template files
  • some value files
  • a (versioned) smudge script able to recognize its execution environment and generate the necessary (non-versioned) final files from the value files or (for more sensitive information) from other sources external to the Git repo.
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250