views:

260

answers:

3

I'm trying to deploy the same rails app to two different locations with different app names, different logos, different stylesheets, etc.

I've got the code working based on an APP_NAME and a HOST_NAME variable I store in environments/production.rb. Now I need to actually deploy it, and I need a better solution than manually editing the environment file on the production machine.

The only way I can see to do it is to create a new production environment - e.g. production_app2 - and define APP_NAME and HOST_NAME differently in them. Is there a better way?

+1  A: 

I think that's a pretty good way.

Where we are we define different environments (e.g. 'staging', 'production', 'production_backup' - giving us a staging.rb, production.rb, production_backup.rb where you can define your specific APP_NAMEs and HOST_NAMEs) and can deploy to each of them using Capistrano. It works just fine.

This is a good link on it: http://www.egtheblog.com/?p=8

DanSingerman
+1  A: 

Because you are actually deploying to two different environments, it seems best to create two different environment files, each with their own settings. Make sure you pick descriptive names for your environment files, not just production2.

You could also store this information in the database, but I don't know if you're willing to accept such a dependency. I guess using a database would only make sense if the number of deployments is too large to manage easily with a few environment files.

molf
+5  A: 

No no no! Don't edit the environment files. I mean, edit them as you need to for things that need to be configured the same for every deployment, but not for things that should be configurable between deployments.

For that, use configuration.

Throw a YAML file in config that looks something like this:

development:
  :app_name: App 1
  :host_name: something.com

test:
  :app_name: App 1
  :host_name: something.com

production:
  :app_name: App 1
  :host_name: something.com

Call it whatever makes sense. Let's say settings.yml.

Now load it with an initializer in config/initializers/settings.rb that looks like this:

SETTINGS = YAML.load_file("#{RAILS_ROOT}/config/settings.yml")[RAILS_ENV]

Now access your configuration like this:

SETTINGS[:app_name]

(If you don't want to change your existing code at all, inside config/initializers/settings.rb add lines that set your existing names like APP_NAME = SETTINGS[:app_name], etc.)

Note that this is one possible implementation of settings configuration, but even if another approach is taken it should be based on deployment-independent configuration. This can be much more easily and maintainably set up to persist between deployments and upgrades than mucking with environment files.

Again, to recap:

  • environment files are for configuration that is the same across all deployments
  • configuration files are for configuration that can change between deployments

Update

For Capistrano based deployments, this is what I use to symlink multiple configuration files in the new current from the shared directory (I think it originally came from an Ezra recipe from EngineYard):

after "deploy:update_code","deploy:symlink_configs"

namespace(:deploy) do  
  task :symlink_configs, :roles => :app, :except => {:no_symlink => true} do
    configs = %w{ database settings }
    configs.map! { |file| "ln -nfs #{shared_path}/config/#{file}.yml #{release_path}/config/#{file}.yml" }
    run <<-CMD
      cd #{release_path} && #{configs.join(' && ')}
    CMD
  end
end
Ian Terrell
Makes sense. But how do I get different settings files on each deployment?
zaius
Presumably they have different databases, too. You use the same strategy that you use for giving them different config/database.yml files. On Capistrano based deployments this usually means symlinking to files in the shared directory.
Ian Terrell
Aha! That's what I was looking for. So each deployment location would have their own settings files, and I use my deployment tool of choice to symlink them. Perfect, thanks!
zaius