在我的 config / database.yml 中使用simple Rails sqlite3 configuration example获取Rails 3.2.6应用程序,我曾经重置我的开发数据库,重新播种它,并准备我的测试数据库只需执行:
$ rake db:reset
$ rake db:test:prepare
在this blog entry关于在不同的数据库引擎上测试带有Travis CI的Rails应用程序之后,我想我会尝试一下,所以我使用Homebrew安装了mysql和postgresql(我在OSX Snow Leopard上,根据brew info
说明进行设置。我安装了相关的gem,并按如下方式配置了数据库和Travis文件:
的Gemfile
# ...
group :development, :test do
# ...
gem 'sqlite3', '1.3.6'
end
group :test do
# ...
# Test mysql on Travis CI
gem 'mysql2', '0.3.11'
end
group :test, :production do
# ...
# Test postgres on Travis CI and deploy on Heroku
gem 'pg', '0.13.2'
end
配置/ database.yml的
sqlite: &sqlite
adapter: sqlite3
database: db/<%= Rails.env %>.sqlite3
mysql: &mysql
adapter: mysql2
username: root
password:
database: my_app_<%= Rails.env %>
postgresql: &postgresql
adapter: postgresql
username: postgres
password:
database: my_app_<%= Rails.env %>
min_messages: ERROR
defaults: &defaults
pool: 5
timeout: 5000
host: localhost
<<: *<%= ENV['DB'] || "sqlite" %>
development:
<<: *defaults
test: &test
<<: *defaults
production:
<<: *defaults
cucumber:
<<: *test
.travis.yml
language: ruby
rvm:
- 1.9.2
- 1.9.3
env:
- DB=sqlite
- DB=mysql
- DB=postgresql
script:
- RAILS_ENV=test bundle exec rake --trace db:migrate
- bundle exec rake db:test:prepare
- bundle exec rspec spec/
before_script:
- mysql -e 'create database my_app_test'
- psql -c 'create database my_app_test' -U postgres
bundler_args: --binstubs=./bundler_stubs
但是,现在,当我运行rake db:reset
时,在成功创建开发数据库之前,我收到一条Couldn't drop db/development.sqlite3
错误消息。因此,似乎现在有多个调用删除相同的数据库(?)。跟踪输出如下:
$ rake db:reset --trace
** Invoke db:reset (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:reset
** Invoke db:drop (first_time)
** Invoke db:load_config (first_time)
** Invoke rails_env (first_time)
** Execute rails_env
** Execute db:load_config
** Execute db:drop
Couldn't drop db/development.sqlite3 : #<Errno::ENOENT: No such file or directory - my_app/db/development.sqlite3>
** Invoke db:setup (first_time)
** Invoke db:schema:load_if_ruby (first_time)
** Invoke db:create (first_time)
** Invoke db:load_config
** Execute db:create
db/development.sqlite3 already exists
# ...
这很奇怪,但至少开发数据库是创建和播种的。真正的问题出现在我运行rake db:test:prepare
时:尽管没有错误消息,以及未创建测试数据库,但开发数据库中的数据却被吹走了(尽管架构仍然存在)。我尝试直接为命令指定Rails环境并得到:
$ rake db:test:prepare RAILS_ENV=test
You have 7 pending migrations:
20120503193649 CreateUsers
# ...
Run `rake db:migrate` to update your database then try again.
运行rake db:migrate RAILS_ENV=test
后,我可以再次运行我的rspec测试。因此,我获得相同结果的rake命令现已更改为:
$ rake db:reset # (with an error)
$ rake db:migrate RAILS_ENV=test
如果我将 config / database.yml 文件更改回简单的仅限sqlite3的配置, db:reset
和 db:test:prepare
按预期工作。
那么,这是否意味着我的mysql和/或postgres设置导致rake任务重复和/或他们搞乱了Rails环境设置?我应该在哪里确认我的环境是否真的设置为与这3个数据库引擎一起正常工作?
查看release notes for Rails 3.2.8.rc2,我发现对ActiveRecord
的更改可能与此问题有关:
RAILS_ENV
和相关的佣金任务时,请勿将development
设置为db:test:prepare
。这导致在使用RSpec时截断开发数据库数据。在使用config.active_record.schema_format = :sql
config / application.rb 有以下解释:
# Use SQL instead of Active Record's schema dumper when creating the database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
我的架构没有约束或特定于数据库的列类型,因此我没有取消注释这一行,但是,鉴于发布说明的内容,我将RAILS_ENV
默认为{{1}可以负责开发环境中已删除的数据。所以,我尝试了一些事情并通过我之前做的事情(在将Rails升级到3.2.8.rc2之后)得到了预期的结果:
development
这样做有点好,但我仍然觉得错误,因为$ rake db:reset # (with an error)
$ rake db:test:prepare RAILS_ENV=test # (with no "pending migrations" issue)
仍有错误,而且在运行rake时必须设置rake db:reset
对我来说没有意义专为测试数据库量身定制的命令。
由于以下修复,似乎升级到Rails 3.2.9解决了这个问题:
RAILS_ENV=test
尝试将structure.sql加载到开发数据库中的错误。修复#8032。Grace Liu +RafaelMendonçaFrança
我现在可以再次重置我的开发数据库,重新播种它,并通过执行以下操作来准备我的测试数据库:
rake db:test:prepare
答案 0 :(得分:9)
您的开发数据库正在被清除,因为ActiveRecord :: Base.configurations将测试数据库设置为“development.sqlite3”。运行rake任务时,yaml配置将被评估为ActiveRecord :: Base.configurations哈希值,此时Rails.env将设置为开发。
如果RAILS_ENV =开发,则test的数据库值将设置为
database: db/development.sqlite3
或其他适配器:
database: my_app_development
您可以使用简单的仅限sqlite配置重现此操作购买将database.yml中的测试块更改为以下内容:
test:
adapter: sqlite3
database: db/<%= Rails.env %>.sqlite3
pool: 5
timeout: 5000
如果检查完整的ActiveRecord :: Base.configurations哈希,您将看到如果未指定RAILS_ENV,则将test设置为使用开发db。如果你要指定'生产'或'暂存',它将被设置为。从控制台:
# rails c
> ActiveRecord::Base.configurations['test']['database']
=> "db/development.sqlite3"
与之相比:
# RAILS_ENV=test rails c
> ActiveRecord::Base.configurations['test']['database']
=> "db/test.sqlite3"
<强>更新强>
您在db:reset中遇到的问题也是因为您的yaml文件被解释一次然后配置了配置。
db:reset将为给定环境调用db:drop和db:setup。但是,如果环境是开发,它还会为测试环境执行这些任务。因此,它成功地删除了开发环境,然后当它执行测试时,配置的数据库键与开发部分相同,因此它不能删除不再存在的内容。以下是Rails.env =='development'时ActiveRecord :: Base.configurations哈希的样子
"development" => {
"adapter" => "sqlite3",
"database" => "db/development.sqlite3",
"pool" => 5,
"timeout" => 5000
},
"test" => {
"adapter" => "sqlite3",
"database" => "db/development.sqlite3",
"pool" =>5,
"timeout"=>5000
},
"production" => {
"adapter" => "sqlite3",
"database" => "db/development.sqlite3",
"pool"=>5,
"timeout"=>5000
}
一旦它在该哈希中,它就不会返回并重新读取database.yml文件。该哈希值是根据 database.yml
生成的development:
adapter: sqlite3
database: db/<%= Rails.env %>.sqlite3
pool: 5
timeout: 5000
test:
adapter: sqlite3
database: db/<%= Rails.env %>.sqlite3
pool: 5
timeout: 5000
production:
adapter: sqlite3
database: db/<%= Rails.env %>.sqlite3
pool: 5
timeout: 5000
答案 1 :(得分:0)
同样的问题,即开发数据库在“rake”之后被破坏。
我的出路“rake RAILS_ENV = test”。
使用ruby 1.9.3p194 Rails 3.2.7 sqlite3。