どうも。
Railsで様々なgemを追加する機会がありますが、その度に依存性に困らされた経験を持つ人は多いと思います。自分もその一人で、何度も都度調べるのも面倒だと思ったので覚書として手順とそれぞれの役割を簡単にまとめます。
Gemfile修正
ここに定義されているgemが、開発時に使えるgemのリストになります。中には明示的に ~>2.0のようにバージョン指定されているgemもあり、このバージョンで無いと動かない、というgemも存在します。基本的にデフォルトのバージョン指定はいじらない方がいいでしょう。
Rubyを使う以上はひたすらこの依存性と付き合っていかなくてはいけないので、なんとなく、ではなく流れ、仕組みを詳細に知っておくべきでしょう。
まだ定義されていないgemはここにgem gemモジュール名と記載して読み込まれるようにする必要があります。
Gemfileをいじったら、いよいよダウンロード&インストールの準備です。当然、ネット繋がってないと失敗します。
bundle install
追加したgemをインストールするのに 必要です。
==> ここが参考になる
bundle update
これは単体で実行すると危険と言われますが、それはすべてgem同士の依存関係の問題からきています。特定のgemの特定のバージョンに依存したgemがある場合、すべてを一度に最新にでもしようとすれば動作しなくなるのは当たり前。
これは適宜やるというよりは、何らかのgemのinstallをするのに現行では依存関係上まずいときなど、必要に応じてやるべきかと。
引数にgem名を渡すことで、特定のgemだけをupdateできます。
brew update
パッケージ管理システム。
==> ここがわかりやすい
homebrewとは何者か。仕組みについて調べてみた - Qiita
RubyだけでなくJavaやその他機能をパッケージ単位でダウンロード&インストールしてくれるツール。どちらかというとlinuxの考え方に近いか。centOSでいうyum, Ubuntuでいうapt-getといえば通じますかね。
そしてこの”brew”自体もソフトウェアであり、updateする必要があります。そんな時にbrew updateとかします。
==> こけたら下記を参照。
rbenv
通常は、ruby-buildとともに使用する。中にはgemのバージョンだけでなく、Rubyのバージョンのせいで動作しないgem(ログイン認証に用いるdeviseとか)もあります。そんな時はRuby自体をupdateする必要に迫られますので、合わせて載せちゃいます。
Rubyの新バージョンをインストールするには
rbenv install Rubyのバージョン名
で狙ったバージョンをインストールしましょう。
私はruby2.2.4をインストールしました。
ruby -v ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin15] rbenv versions system 2.0.0-p451 * 2.2.4 (set by RAILS_ROOTのパス/.ruby-version
Rubyのinstall後もまだ安心はできません。Rails Consoleを立ち上げようとしたら、bundler関連で、下記のように怒られました(´・ω・`)
rbenv: rails: command not found The `rails' command exists in these Ruby versions: 2.0.0-p451
2.2.4がNEEEEEE!!
そもそも、bundle installのbundlerというのもソフトウェアです。これ自体のバージョンも関係している模様で、それが利用中のRubyのバージョンとあっていないと怒られるとのこと。
==> 下記を参照
じゃあ、仕方ないから、bundlerも入れ直しましょう。※1
bundle install
今度は大丈夫なはず。
rails c rbenv: rails: command not found The `rails' command exists in these Ruby versions: 2.0.0-p451
が、駄目っ・・・!
よくよくエラーメッセージを見ると、railsを入れ直す必要がありました。時間がかかるな〜(´・ω・`)
gem install rails
さて様子は?
rails c Running via Spring preloader in process 43023 RAILS_ROOTのパス/vendor/bundle/ruby/2.2.0/gems/spring-1.7.1/lib/spring/application.rb:175: warning: Insecure world writable dir RAILS_ROOTのパス in PATH, mode 040757 Loading development environment (Rails 4.2.4) 2.2.0 :001 >
よし、成功。
最終的にそれぞれのパッケージのバージョンは下記の通りになりました。
rails -v Rails 4.2.4 ruby -v ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin15] rbenv -v rbenv 1.0.0 bundler -v Bundler version 1.12.5
いやぁ〜長い戦いだった。。
そもそもこのタイミングでRubyバージョン変更するとは思わなんだ。deviseっていうgemを入れるために追加で苦労する羽目になったが、基本を押さえておけばトラブったところで無問題。この程度の障害で俺を超えることはできぬぅ!
rvm
Rubyをインストールして共存させたいときに用いるパッケージです。Rubyは他の言語以上にバージョンによる制限というか影響が大きいので、同時に複数のバージョンを使えるようにしておきたいという要望は多いんでしょう。
ここだけだと、rbenv(+ruby-build)とかぶりますが、単にRubyをインストールするだけならこちらでもいいでしょう。基本的にrvmでできることはrbenvに必要なgemsetを追加すればいいんですが、いちいち調べるのも面倒でしょうから。
==> 細かな違いは下記参照。
最大の注意点
※1の部分で、実はさらにこけていました。rbenvとrvmの両刀は危険ということです。あろうことか私はrbenvで入れたRubyをなぜかrvmで入れなおしてしまい、おかげで正しくBundlerが立ち上がらなくなってしまいました。
bundle -v /Users/ユーザ名/.rbenv/versions/2.2.4/lib/ruby/2.2.0/rubygems/dependency.rb:315:in `to_specs': Could not find 'bundler' (>= 0) among 14 total gem(s) (Gem::LoadError) Checked in 'GEM_PATH=/Users/ユーザ名/.rvm/gems/ruby-2.2.4:/Users/ユーザ名/.rvm/gems/ruby-2.2.4@global', execute `gem env` for more information from /Users/ユーザ名/.rbenv/versions/2.2.4/lib/ruby/2.2.0/rubygems/dependency.rb:324:in `to_spec' from /Users/ユーザ名/.rbenv/versions/2.2.4/lib/ruby/2.2.0/rubygems/core_ext/kernel_gem.rb:64:in `gem' from /Users/ユーザ名/.rbenv/versions/2.2.4/bin/bundle:22:in `<main>' </main>
上記エラー内容にrvm、とあるので原因は明らか。こうなってしまったら、解決策は
gem install bundler
はい、入れ直しです。どれだけこければ気が済むんだ><
==> この問題に関しては先駆者がいました。StackOverflow万歳ヽ('A`)ノ
bundle -v Bundler version 1.12.5
今度はこけませんでした。
上記の様にbundler周りで色々こけている場合、他にも影響している可能性が考えられます。案の定、私の場合はrakeコマンドが死んでました
というわけで解決します。
rake routes rake aborted! Gem::LoadError: You have already activated rake 10.4.2, but your Gemfile requires rake 11.1.2. Prepending `bundle exec` to your command may solve this. /Users/ユーザ名/.rvm/gems/ruby-2.2.4/gems/bundler-1.12.5/lib/bundler/runtime.rb:35:in `block in setup' ...
こういうエラーが出たら、bundle execをつけてコマンド実行すれば、エラーは出ません。
bundle exec rake routes Prefix Verb URI Pattern Controller#Action maker_index GET /maker/index(.:format) maker#index root GET / maker#index makers GET /makers(.:format) makers#index POST /makers(.:format) makers#create new_maker GET /makers/new(.:format) makers#new edit_maker GET /makers/:id/edit(.:format) makers#edit maker GET /makers/:id(.:format) makers#show PATCH /makers/:id(.:format) makers#update PUT /makers/:id(.:format) makers#update DELETE /makers/:id(.:format) makers#destroy
うん、動いた。
ただ、これは毎回頭にbunldle execつけないといけないっぽいな(´・ω・`)そもそもbundlerを更新しただけで死ぬって設計思想からしてどうかと思うんだがな。。
エラー内容とその解決方法自体は他のどんなパッケージも、同様。落ちる原因はまず間違いなくバージョンによる依存関係の問題だから、どれとどれのバージョンの関係に問題があるのかをはっきりさせましょう。
ここに至るまでに本当にQiitaには度々お世話になりっぱなしで、最高にありがたいサイトだと思います。考案者は天才。
そしてこれだけ地雷を踏んだんだから、その経験はこうしてある意味啓蒙活動として広める&記録に残すのは義務だと思っているので、時間をかけてでもまとめ上げるのは結構楽しいものです。これからも続けていきます。
これで何度もググり直す必要がなくなるだろう。