简体   繁体   中英

Rails 3 - rake tasks to work with multiple database connections

Let's say I have s different database connections...

Right now for the purposes of this example let's only be concerned with development. When I run 'rake db:setup' it only creates development because from the rake task perspective the other connection is another environment. I could pass in the other connection as the RAILS_ENV to create the database. However, the problem comes in with how we've defined our database connections. I'd rather not undo this as it makes management and deployment much easier. What we've done is this...

In our database.yml we've added the following code.

databases_file = File.join(Rails.root.to_s, "config", "databases", "#{Rails.env.to_s}.yml")
IO.read(databases_file) if File.exist?(databases_file)

Then in a databases sub-folder under config we've created the different environment yml files.

So in development.yml we have...

development:
  ... details ...

logging:
  ... details ...

Now if I set RAILS_ENV to 'logging' it will never load the file since the file is called development.yml. Thus it will never find the logging connection.

If I consolidate all these settings back into the database.yml file then we're back to not checking in the database.yml into the git repo and having to manually create it on the development machines for new hires and such. We'd also have to change our deploy process to start putting the file in place on the lower environments. (Our production process already supports this)

You could use environment variables to manage these. You could have a single database.yml with things defined such as:

development:
  database: ENV['DEVELOPMENT_DATABASE']

And then set the environment variables in your .bashrc/.zshrc .

We have multiple databases and we use branches heavily... so I came up with this solution to create multiple databases and tie their names to the branch being worked on...

# config/database.yml
<%=
    databases_file = File.join(Rails.root.to_s, "config", "databases", "#{Rails.env.to_s}.yml")
  if Rails.env.development? || Rails.env.test?
    branch = ENV['BRANCH'] || `git branch --no-color 2> /dev/null`.chomp.split("\n").grep(/^[*]/).first[/(\S+)$/,1].sub("-", "_")
    puts "Using databases for #{branch}"
    IO.read(databases_file).gsub!("<branch>", branch) if File.exist?(databases_file)
  else
    IO.read(databases_file) if File.exist?(databases_file)
  end
%>

And then you create a database file for each environment. In the development.yml and test.yml you use the token to let this script look for what it needs to in order to do replacement. So an example file would look like this.

# config/databases/development.yml
development:
  adapter: mysql2
  host: 127.0.0.1
  database: <branch>_dev
  username: user
  password: pass

versions:
  adapter: mysql2
  host: 127.0.0.1
  database: <branch>_versions
  username: user
  password: pass

reporting:
  adapter: mysql2
  host: 127.0.0.1
  database: <branch>_reporting
  username: user
  password: pass

ods:
  adapter: mysql2
  host: 127.0.0.1
  database: <branch>_ods
  username: user
  password: pass

I then extended the rake tasks to handle multiple databases

This is where most of the work went in. Therefore, I'm going to leave it out of the answer and make you work for it! No actually, it's just a big large mess that I'm not proud of and would love time to fix it, but haven't found any. I don't want to lead anyone down the wrong path but if you have questions just get me a message and I'll be happy to help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM