RoR: how do I test my app against multiple databases?

我怕爱的太早我们不能终老 提交于 2019-12-21 06:28:45

问题


I started deploying my latest RoR app on Heroku, which required me to start using PostgreSQL -- I'd previously been using SQLite and MySQL. I wanted a dead-simple way to continually do red/green testing against all three databases to make sure I didn't break anything in the heat of development.

What's a good way to do this?


回答1:


@awendt kindly pointed out that I could answer my own question.

It turns out the recipe is rather simple. The secret is to use a environment variable to tell Rails which db you want to use.

1. Modifying your files

In config/database.yml, include ERB constructs like this:

test:
<% if (ENV["RAILS_DB"] == "PostgreSQL") %>
  adapter: postgresql
  encoding: unicode
  database: bd_test
  pool: 5
  username: <%= ENV['POSTGRESQL_USERNAME'] || 'root' %>
  password: <%= ENV['POSTGRESQL_PASSWORD'] || '' %>
<% elsif (ENV["RAILS_DB"] == "MySQL") %>
  adapter: mysql
  encoding: utf8
  reconnect: false
  database: bd_test
  pool: 5
  username: <%= ENV['MYSQL_USERNAME'] || 'root' %>
  password: <%= ENV['MYSQL_PASSWORD'] || '' %>
  socket: <%= ENV['MYSQL_SOCKET'] || '/tmp/mysql.sock' %>
<% else %>
  # default to SQLite
  adapter: sqlite3
  database: db/test.sqlite3
  pool: 5
  timeout: 5000
<% end %>

Note 1: I've only shown it for the test environment. In fact, that's the only one I've modified, since (supposedly) it provides enough coverage to tell me if all three databases are properly supported.

Note 2: You don't need to use environment variables to set username and password -- that's just something I prefer to do since it avoids exposing passwords in a commonly viewed file.

Similarly, extend Gemfile as follows (note that your version numbers may vary):

source 'http://rubygems.org'
gem 'rails', '3.0.3'
case ENV["RAILS_DB"]
when "PostgreSQL"
  gem 'pg', '0.10.0'
when "MySQL"
  gem 'mysql2'
else
  gem 'sqlite3', '1.3.3'
  gem 'sqlite3-ruby', '1.3.3', :require => 'sqlite3'
end
...

2. Add conditions to your code

Despite the best efforts of the Rails development team, there are a few spots where ActiveRecord constructs aren't compatible across all flavors of database. In these cases, you can condition your code on ActiveRecord::Base.connection.adapter_name. Here's an example from one of my migration files:

file: migrate/20110129023453_create_cached_web_pages.rb

def self.up
  create_table :cached_web_pages do |t|
    t.string    :key             
    if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
      t.binary    :value
    else
      t.binary    :value, :limit => 16777215
    end
  end
end
...

3. Running and testing

You can now select a database simply by setting the RAILS_DB environment variable, but there's a catch: you have to run bundle install each time to set up the appropriate database adaptor from the Gemfile. Fortunately, that's exactly what the test code does. So, for example, I can run rspec's autotest in two windows:

$ RAILS_DB=SQLite autotest

and

$ RAILS_DB=PostgreSQL autotest

Now I can hack away at my files and autotest will quietly alert me if I've broken anything as I go along.



来源:https://stackoverflow.com/questions/5316645/ror-how-do-i-test-my-app-against-multiple-databases

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!