Sooey

2016-05-21 23:31:51 +0900

CircleCI上でのRails 5.0.0.rc1 + factory_girl_railsのビルドがPG::UndefinedTableで失敗する件

以下のような構成のRailsアプリをCircleCIでビルドする際、

  • Rails 5.0.0.rc1
  • factory_girl_rails 4.7.0

rake db:create db:schema:loadrake db:create db:structure:loadのフェーズで以下のような例外が発生してビルドが失敗するようになった。

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "posts" does not exist
LINE 8:                WHERE a.attrelid = '"posts"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
             (SELECT c.collname FROM pg_collation c, pg_type t
               WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation),
                     col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
               WHERE a.attrelid = '"posts"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum    

スタックトレースやrake db:schema:load fails - CircleCIを見た結果、以下のような流れになっていることがわかった。

  • Railsのロード過程でfactory_girl_rails/railtie.rbが読み込まれる
  • FactoryGirl.find_definitionsが呼び出される
  • spec/factories/*.rbが読み込まれる
  • モデルクラスがロードされる
  • モデルクラスに対応するテーブルがまだ存在しないため例外が発生

Rails 5.0がリリースされるまでの過程で解消するのかもしれないが、ひとまずGemfileではfactory_girl_railsrequireしないようにして、

group :test do
  ...
  gem 'factory_girl_rails', '4.7.0', require: false
  ...
end

そのかわりにspec/spec_helper.rbで明示的にrequireする形にして問題を回避することにした。

#
# factory_girl_rails
#
# To prevent PG::UndefinedTable excetion during `rake db:structure:load` on
# CircleCI build, we don't require the gem in Gemfile.
# Because of this, we need to require it explicitly here.
#
# See: https://circleci.com/docs/ruby-exception-during-schema-load/
#
require "factory_girl_rails"