railsコマンドでエラー cannot load such file -- bundler/setup (LoadError)

  • 3
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

環境

  • Ruby 2.2.3
  • Rails 4.2.4
  • capistrano 3.4.0
  • capistrano-bundler 1.1.4
  • capistrano-rails 1.1.6
  • capistrano-rbenv 2.0.4
  • capistrano3-unicorn 0.2.1

概要

developmentサーバーから、capistranoを使用し、productionサーバーへdeploy。
productionでrails runnerコマンドをたたくと下記のエラーが出た。
ちなみに、rails cとか、他のrailsコマンド全般でエラーが出る。

$ rails runner Tasks::TaskName.execute
/home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- bundler/setup (LoadError)
        from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/commands.rb:33:in `<module:Spring>'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/commands.rb:4:in `<top (required)>'
        from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:77:in `preload'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:143:in `serve'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:131:in `block in run'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:125:in `loop'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:125:in `run'
        from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application/boot.rb:18:in `<top (required)>'
        from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from -e:1:in `<main>'

調査

いろいろとググってみたら、

下記を実行しろやら、

$ rbenv exec bundle install

springを再起動しろやら、

$ spring stop
Spring stopped.

$ bin/spring

いろいろ情報が出てくるが、何をやっても状況変わらず。

で、springって何だろと思って、Gemfileを見てみたら、productionではインストールされないようになっている!

Gemfile
group :development do
  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'

  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
end

productionで読み込まれないはずなのになんでspringのエラー出るの?と思っていたら下記の記事を発見。
私と同じ道をたどっている。。。

[参考] http://qiita.com/rojiuratech/items/759c2d62907a2a36e340

結局、bin/railsのファイルの中身に問題があった。

productionでは、springはインストールしてないが、bin/railsファイルで読み込もうとしている。
どうしてこんなことになるのかというと、ソースコードは、developmentでgitにpushしたものを、productionでpullしているため、本番のbin/railsのファイルの中身も、development用のままになっていた。productionでは、springをloadする必要はない。

  • 変更前(development用)
bin.rails
#!/usr/bin/env ruby
begin
  load File.expand_path('../spring', __FILE__)
rescue LoadError => e
  raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
  • 変更後(production用)
bin.rails
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'

ファイルの中身を変更したら、railsコマンドが動くようになった。

しかし、capistranoを使ってdeployをしているので、毎回手動でファイルの中身を編集するわけにはいかない。

どうやら、rake rails:update:binというコマンドで、ファイルの書き換えができるようだ。

$ rake rails:update:bin
       exist  bin
   identical  bin/bundle
    conflict  bin/rails
Overwrite /home/user/app/app_name/releases/20160308034224/bin/rails? (enter "h" for help) [Ynaqdh] Y
       force  bin/rails
    conflict  bin/rake
Overwrite /home/user/app/app_name/releases/20160308034224/bin/rake? (enter "h" for help) [Ynaqdh] Y
       force  bin/rake
   identical  bin/setup

bin/rakeにもspringの記述があるのね。

とりあえず、原因は判明。

残る問題点

ただ、deploy後にrake rails:update:binを適用するには、
capistranoのdeploy後に、このコマンドが実行されるようにすればいいのか?
それとも、deploy.rbのlinked_dirsの設定を使って、springを読み込まない本番用のbin/rails, bin/rakeを用意して、シンボリックリンクを貼るようにすべきなのか?それとももっと良い方法があるのか、調査中です。