12

Rails3.2.6アプリのconfig/database.ymlにある簡単なRailssqlite3構成例を使用して、開発データベースをリセットし、再シードして、次の手順を実行するだけでテストデータベースを準備していました。

$ rake db:reset
$ rake db:test:prepare 

さまざまなデータベースエンジンでTravisCIを使用してRailsアプリケーションをテストすることに関するこのブログエントリを見て、試してみようと思ったので、Homebrew(OSX Snow Leopardを使用しています)を使用してmysqlとpostgresqlをインストールし、セットアップしました指示に従って。関連するgemをインストールし、データベースとTravisファイルを次のように構成しました。brew info

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

config / 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:resetCouldn'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つのデータベースエンジンで正しく動作するように実際に設定されているかどうかを確認するには、どこを探す必要がありますか?

編集

Rails 3.2.8.rc2のリリースノートを見ると、ActiveRecordこの質問に関連する可能性のある変更が見つかりました。

  • および関連するレーキタスクを使用する場合RAILS_ENVは、に設定しないでください。これにより、RSpecを使用するときに開発データベースデータが切り捨てられていました。RC2で使用時に再度修正されましたdevelopmentdb:test:prepareconfig.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デフォルトdevelopmentで開発環境で削除されたデータの原因となる可能性があると考えました。それで、私はいくつかのことを試し、以前に行ったことを実行することで期待される結果を得ました(Railsを3.2.8.rc2にアップグレードした後):

$ rake db:reset # (with an error)
$ rake db:test:prepare RAILS_ENV=test # (with no "pending migrations" issue)

これは少し良いですが、まだエラーがあるので私には間違っているように見えます。テストデータベース用に特別に調整されたrakeコマンドを実行するときrake db:resetに設定する必要があるのは意味がありません。RAILS_ENV=test

アップデート

Rails 3.2.9にアップグレードすると、次の修正によりこの問題が解決するようです。

  • rake db:test:preparestructure.sqlを開発データベースにロードしようとするバグを修正します。修正#8032。

GraceLiu+RafaelMendonçaFrança

これで、開発データベースを再度リセットして再シードし、次の手順を実行するだけでテストデータベースを準備できます。

$ rake db:reset
$ rake db:test:prepare 
4

2 に答える 2

9

ActiveRecord :: Base.configurationsのテストデータベースが「development.sqlite3」に設定されているため、開発データベースが削除されています。rakeタスクが実行されると、yaml構成がActiveRecord :: Base.configurationsハッシュに評価され、その時点でRails.envが開発に設定されます。

RAILS_ENV = developmentの場合、テストのデータベース値は次のように設定されます。

database: db/development.sqlite3

または別のアダプターの場合:

database: my_app_development

database.yml内のテストブロックを次のように変更するだけで、単純なsqliteのみの構成でこれを再現できます。

test:
  adapter: sqlite3
  database: db/<%= Rails.env %>.sqlite3
  pool: 5
  timeout: 5000

ActiveRecord :: Base.configurationsハッシュ全体を調べると、RAILS_ENVが指定されていない場合、テストが開発データベースを使用するように設定されていることがわかります。また、「本番」または「ステージング」を指定すると、それに設定されます。コンソールから:

# 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
于 2012-08-07T19:18:34.323 に答える