RoR:我如何针对多个数据库测试我的应用程序?

时间:2011-03-15 19:03:32

标签: mysql ruby-on-rails sqlite postgresql rspec

我开始在Heroku上部署我最新的RoR应用程序,这需要我开始使用PostgreSQL - 我以前一直在使用SQLite和MySQL。我想要一种简单的方法来持续对所有三个数据库进行红色/绿色测试,以确保我没有在开发的热量中破坏任何东西。

这样做的好方法是什么?

1 个答案:

答案 0 :(得分:0)

@awendt善意地指出我可以回答我自己的问题。

事实证明配方相当简单。秘诀是使用环境变量告诉Rails你想要使用哪个db。

1。修改文件

config/database.yml中,包括这样的ERB结构:

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 %>

注1:我只在测试环境中显示过它。事实上,这是我修改过的唯一一个,因为(据说)它提供了足够的覆盖率来告诉我是否所有三个数据库都得到了适当的支持。

注意2:您不需要使用环境变量来设置用户名和密码 - 这只是我喜欢做的事情,因为它避免了在常见文件中暴露密码。

同样,按如下方式扩展Gemfile(请注意您的版本号可能会有所不同):

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。为代码添加条件

尽管Rails开发团队做出了最大的努力,但有一些地方ActiveRecord构造在所有类型的数据库中都不兼容。在这些情况下,您可以在ActiveRecord::Base.connection.adapter_name上调整代码。以下是我的一个迁移文件中的示例:

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。运行和测试

现在可以通过设置RAILS_DB环境变量来选择数据库,但是有一个问题:每次都必须运行bundle install以从Gemfile设置适当的数据库适配器。幸运的是,这正是测试代码所做的。因此,例如,我可以在两个窗口中运行rspec的自动测试:

$ RAILS_DB=SQLite autotest

$ RAILS_DB=PostgreSQL autotest

现在我可以破解我的文件,如果我在进行任何事情的话,自动测试会悄悄提醒我。