为什么我需要在 Ubuntu 12.04 Precise 下显式 运行 Rails 迁移?

Why do I need to explicitly run Rails migrations under Ubuntu 12.04 Precise?

我正在构建一个 Rails 5 应用程序,我正在使用 Rspec 进行测试。我过去曾多次将 Travis 用于 Rails 应用程序,但他们使用的是 MiniTest 和 Rails 4.

我可以 运行 在本地测试:

joenyland@MacBook-Pro ~/Code/acrm $ rake db:drop
Dropped database 'db/development.sqlite3'
Database 'db/test.sqlite3' does not exist
joenyland@MacBook-Pro ~/Code/acrm $ RAILS_ENV=test bundle exec rake
/Users/joenyland/.rvm/rubies/ruby-2.3.0/bin/ruby -I/Users/joenyland/.rvm/gems/ruby-2.3.0@acrm/gems/rspec-core-3.5.4/lib:/Users/joenyland/.rvm/gems/ruby-2.3.0@acrm/gems/rspec-support-3.5.0/lib /Users/joenyland/.rvm/gems/ruby-2.3.0@acrm/gems/rspec-core-3.5.4/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
*.............................

Pending: (Failures listed here are expected and do not affect your suite's status)

  1) SessionsHelper add some examples to (or delete) /Users/joenyland/Code/acrm/spec/helpers/sessions_helper_spec.rb
     # Not yet implemented
     # ./spec/helpers/sessions_helper_spec.rb:14


Finished in 1.87 seconds (files took 15.63 seconds to load)
30 examples, 0 failures, 1 pending

但是当 Travis 运行 进行测试时,它失败了:

0K$ bundle exec rake
/home/travis/.rvm/rubies/ruby-2.3.0/bin/ruby -I/home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib:/home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-support-3.5.0/lib /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
/home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:572:in `check_pending!':  (ActiveRecord::PendingMigrationError)

Migrations are pending. To resolve this issue, run:

    bin/rails db:migrate RAILS_ENV=test

    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:585:in `load_schema_if_pending!'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:591:in `block in maintain_test_schema!'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:822:in `suppress_messages'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:596:in `method_missing'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:591:in `maintain_test_schema!'
    from /home/travis/build/MasterRoot24/acrm/spec/rails_helper.rb:27:in `<top (required)>'
    from /home/travis/build/MasterRoot24/acrm/spec/models/client_spec.rb:1:in `require'
    from /home/travis/build/MasterRoot24/acrm/spec/models/client_spec.rb:1:in `<top (required)>'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1435:in `load'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1435:in `block in load_spec_files'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1433:in `each'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/configuration.rb:1433:in `load_spec_files'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:100:in `setup'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:86:in `run'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:71:in `run'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib/rspec/core/runner.rb:45:in `invoke'
    from /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/exe/rspec:4:in `<main>'
/home/travis/.rvm/rubies/ruby-2.3.0/bin/ruby -I/home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib:/home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-support-3.5.0/lib /home/travis/build/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb failed

我的 Travis 配置:

language: ruby
cache: bundler

我知道明显的解决方案是在 Travis 配置中添加一个 before 脚本到 运行 rails db:migrate RAILS_ENV=test。但是,我的问题是为什么我以前从来不需要这样做突然需要这样做?

Rspec 5 的 Rspec 实现是否发生了一些变化,这意味着现在迁移不是 运行 before tests automatically? (我假设这就是过去发生的事情...)

我应该补充说 spec/rails_helper.rb 包含以下行:

# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

...所以看起来 应该 是 运行迁移。

2016 年 3 月 11 日更新

在 Travis 的帮助下,我成功地在 Travis 的基础设施之外重现了这个问题。

Travis 运行s 建立在他们基于容器的基础架构上,他们的镜像 (quay.io/travisci/travis-ruby) 基于 Ubuntu 12.04.5 (Precise)。

我现在可以像这样重现问题:

docker run -it ubuntu:precise /bin/bash

apt-get update && apt-get install git bash-completion curl nodejs -y && gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 && \curl -sSL https://get.rvm.io | bash -s stable && source /etc/profile.d/rvm.sh && rvm install 2.3.0 && git clone --depth=50 --branch=master https://github.com/MasterRoot24/acrm.git MasterRoot24/acrm && cd MasterRoot24/acrm && rvm use 2.3.0 && gem install bundler && export BUNDLE_GEMFILE=$PWD/Gemfile && bundle install --jobs=3 --retry=3 --deployment --path=${BUNDLE_PATH:-vendor/bundle} && bundle exec rake

root@e4f741e8c189:/MasterRoot24/acrm# bundle exec rake
/usr/local/rvm/rubies/ruby-2.3.0/bin/ruby -I/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/lib:/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-support-3.5.0/lib /MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/rspec-core-3.5.4/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
/MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:572:in `check_pending!':  (ActiveRecord::PendingMigrationError)

Migrations are pending. To resolve this issue, run:

    bin/rails db:migrate RAILS_ENV=test

    from /MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:585:in `load_schema_if_pending!'
    from /MasterRoot24/acrm/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.0.1/lib/active_record/migration.rb:591:in `block in maintain_test_schema!'

如果我在 macOS 10.12 或 Debian Jessie 上本地执行相同的操作,测试会通过并且我不会被要求 运行 手动迁移。

为什么我需要 运行 在 Ubuntu 12.04 下手动迁移,而不是在任何其他 OS 下?

所以我能够解决这个问题是 ActiveRecord 与 SQLite 接口的方式中的一个错误 gem 并且实际上发生的事情是 ActiveRecord 正在向 SQLite 提交语句以记录已完成的迁移和SQLite 只存储了一些已完成的迁移。

只有在使用 SQLite v3.7.9(不支持多插入语句)时才会出现此问题,这是可用于 Ubuntu 12.04 Precise 的最新 SQLite 版本。这解释了为什么我在 Travis 中 运行 测试时才遇到这个问题,因为这是他们在那里使用的默认发行版和版本。

我提出了一个 GitHub 问题 here and a fix was provided in fd87169

如果您遇到同样的问题,为了利用此修复程序,您需要使用包含它的 Rails 版本,而在撰写本文时,还没有包含它的版本,所以我只是来自 master 运行 我的 Gemfile 中有以下内容:

gem 'rails', github: 'rails/rails'

虽然这应该包含在 Rails 的未来版本中,但我们只需要等待...