rbenv を用いて Ruby をシステム全体にインストールする方法

注:本記事はMacOS X や Linux などのUnix系OS向けとなります。WindowsでもCygwin環境を使えば出来るかもしれませんが。

MacOS Xを使っていると、標準でインストールされている ruby が1.8系なので、最新のRuby on Railsを用いたウェブアプリ開発が出来なかったりして困ります。そこで最新のRubyをインストールすることになりますが、バージョンアップ時の手間を考えると、ソースコードをもってきてビルドするという手順を出来るだけ簡単にしておきたいところです。

そのような要望に応えるツールとして rvmrbenv といったものがあります。本記事では rbenv を用いてシステム全体に新しいバージョンのRubyを適用する方法を記します。

なお、Rubyのビルドに必要なツール類(コンパイラやライブラリなど)のインストールについては省略します。

rbenv のインストール

本記事では、/usr/local 以下に rbenv および Ruby をインストールするものとします。システム全体でのインストールとするため、作業は特権ユーザ(root)にて行います。

まず、/usr/local 以下に rbenv を github からもってきます。

# mkdir -p /usr/local
# git clone https://github.com/sstephenson/rbenv.git

rbenv 以下にpluginsディレクトリを作成し、その下に ruby-build を持ってくる。

# cd rbenv
# mkdir plugins
# git clone https://github.com/sstephenson/ruby-build.git

rbenv と ruby-build は gitで取ってくるのではなく、パッケージを取ってきて展開するという方法でも構いませんが、git pullするだけでアップデートと後々楽になるので、ここでは git clone しています。

rbenv の環境設定を行います。 システム全体でrbenvを使用したい場合、MacOS Xの場合、/etc/bashrc に以下を追加するなどが良いでしょう。 ((ユーザごとで設定する場合は、$HOME/.bash_profile などに記載してください。))

export RBENV_ROOT=/usr/local/rbenv
export PATH="/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH"
eval "$(rbenv init -)"

Linuxの場合、/etc/profile.d/rbenv.sh などのファイルを作成して、その中に上記を記述するというのでも良いでしょう。

その後、rbenv の環境設定を有効化します(上記の追加内容の一連のコマンドを実行したり、source コマンドを用いて上記の設定を読みこませたり、ログインしなおしたりしてください)。設定が成功しrbenv にパスが通っているかどうかは、以下のコマンドで確認ができます。

# which rbenv
/usr/local/rbenv/bin/rbenv

/usr/local/rbenv/bin/rbenv が返ってきていればOKです。

Rubyのビルド

次にRubyをビルドします。rbenv を使えば、バージョンを指定してRubyのビルドを行うことができます。((rbenv内の整合性がとれていない場合にrbenvコマンドは失敗するかもしれません。その場合は rbenv rehashコマンドで整えるなどして再度実行してみてください。))

たとえば、ruby 2.0.0-p0 をインストールしてみます。

# rbenv install 2.0.0-p0

Rubyのビルドに必要なツールが揃っていれば、ビルドに成功するはずです。成功しない場合、何かツールが欠けているので、エラーメッセージに従って足りないツールをインストールしてください。 ((opensslやreadlineなどをあらかじめシステムにインストールしておき、ビルド時にそれを参照するようにすることも可能ですが、ここではrbenvに依存するライブラリの準備も任せています。))

インストールされているRubyを確認します。これには rbenv versions コマンドを使用します。

# rbenv versions
  system
* 2.0.0-p0 (set by /usr/local/rbenv/version)

ここで、system に * が付いている場合は、標準のRuby(1.8系)が選択されている状態ですので、ruby global コマンドを用いて、先ほどインストールしたrubyを利用するように変更してください。

# rbenv global 2.0.0-p0

バージョンを指定したRubyのインストールは完了です。実行されるrubyコマンドのパスとバージョンを確認してください。

# which rbenv
/usr/local/rbenv/shims/ruby
# ruby -version
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.3.0]

以上です。Enjoy your Ruby life!

RubyMine (またはIntelliJ IDEA)で、deviseのヘルパーが認識されない問題を回避する方法

Ruby on Railsでのユーザ認証機能には、定番として devise がよく用いられます。

また、Ruby on Railsでのアプリは、JetBrainsRubyMine (もしくは同機能を包含した IntelliJ IDEA)を用いると非常に効率よく開発を進めることができます。

しかし、この便利なdeviseを用いたRailsプロジェクトを、RubyMineIntelliJ IDEAで編集する場合に、deviseが提供するcurrent_userやuser_signed_in? ((Userクラスをdeviseを用いて作成した場合)) などの便利なヘルパーメソッドを認識してくれないという問題が発生します。

IDEが認識をしていないだけですので、実際にそれらのヘルパーメソッドを用いて作成した機能は正常動作するのですが、それらのヘルパーメソッドを用いる箇所で、IDEによる補完機能の恩恵を受けることが出来なくなります。また、文法違反の可能性があるとして警告が出てしまうため、他の本当に対処すべき問題を埋もれさせてしまう(潜在的なバグを見つけにくくなる)という問題もはらみます。

これは、RubyMineが動的に生成されたメソッドを認識して文法チェックすることが出来ないために発生していると思われます。

そこで、その問題を回避するため、以下のようなヘルパーを app/helpers/application_helper.rb に追記します(この例は、ログイン用にdeviseで作成したモデルのクラスがUserの場合)。

# IDEの補完機能を有効にするため、Deviseのヘルパを宣言
def authenticate_user!(opts={})
  opts[:scope] = :user
  warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def user_signed_in?
  !!current_user
end

def current_user
  @current_user ||= warden.authenticate(:scope => :user)
end

def user_session
  current_user && warden.session(:user)
end

上記に追加したヘルパーメソッド群、元々のdeviseの中ではより柔軟に様々なモデルに対して適用できるように以下のようなコードがevalで動的に処理されます。(Github上の該当ファイル)

def authenticate_#{mapping}!(opts={})
    opts[:scope] = :#{mapping}
      warden.authenticate!(opts) if !devise_controller? || opts.delete(:force)
end

def #{mapping}_signed_in?
  !!current_#{mapping}
end

def current_#{mapping}
  @current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
end

def #{mapping}_session
  current_#{mapping} && warden.session(:#{mapping})
end

この #{mapping} の部分は devise 管理下で作成されたモデル名を元にして引数として渡されたものと置き換えられます。たとえば、Userモデルクラスの場合は #{mapping} の部分は user となります。

上記のような、任意のモデル名に対応することが可能なヘルパーメソッド定義となっているものを、特定モデルに特化したヘルパメソッド定義のせいで発生している問題を、特定のモデルに特化したヘルパーメソッドを定義することで回避するという対策です。

同様の方法で動的にメソッドを追加している箇所は他にもあるため、deviseを用いてコーディングをしている時に補完が働かないという現象が発生した場合は、必要に応じて同様の処理を行うと解決させられるかもしれません。

ところで余談ですが、RubyMineやIntelliJ IDEAは、サムライズムさんのような日本の代理店から日本的な商慣行での購入も可能です。開発効率を劇的に向上してくれる非常にパワフルなIDEですので、まずは30日間の無料体験をしてみてはいかがでしょうか。((とはいえ、これを確認に来た方はすでにRubyMineかIntelliJ IDEAユーザさんなのではないかと思いますが。))

なお、Railsでの devise の導入方法や使用方法については日本語のブログでの解説記事も多数ありますので、本エントリでは割愛いたします。