2014年8月17日日曜日

Haxe 事始め(2) OpenFL で作成したプロジェクトの基本構成を見てみよう

前回の記事では OpenFL のサンプルである PiratePig を動かしてみるところまで話が進んだ。

手元にソースがあるので、 OpenFL の基本を学ぶ材料として、PiratePig の実装を見て行こう。

プロジェクトの基本構成


まずプロジェクトディレクトリだが次の構成でプロジェクトは作成されているのが見て取れる。



Assets がアプリ用リソースのディレクトリ、 Source がアプリ用のソースコードを置くディレクトリとなっている。
Pirate Pig.hxproj は FlashDevelop という IDE 用のファイルで、 Haxe ではよくつかわれる IDE だ。

project.xml が OpenFL (というよりもベースにしている lime ) で重要なファイルとなる。
上にあげた各ディレクトリは、このファイルで定義されている (ので、パスや名前を変えることもできる) 。

少々発展的な内容になるが、 OpenFL は lime という、また別の haxe ライブラリに依存している。
lime は haxe でのクロスプラットフォームネイティブアプリ開発基盤となるライブラリで、
前回、大変便利に開発環境が整ったのは、だいたいこのライブラリのおかげだ。

次は、PiratePig の project.xml を見ていこう。

プロジェクト設定ファイル



さっそく <meta /> タグと <app /> タグが登場するが、ここはあまり説明しなくても迷わないだろう。
それぞれアプリケーションの情報を表すタグと、アプリケーションの基本となる設定のタグだ。
app タグではアプリケーションのエントリポイントなどが指定できる。
PiratePig では priatepig.PiratePig がエントリポイントとなる main クラスとして指定されているのがわかる。

<windows /> タグはアプリケーション実行時のウィンドウサイズなどが指定できるタグだ。
フルスクリーンで起動する場合や解像度の変更などもここで指定する。
もちろん、スマホアプリをターゲットにする場合は縦持ち・横持ちもここで指定することとなる。

<source /> <haxelib /> <icon /> タグもそのままだ。特に <source /> タグでソースコードディレクトリが指定されている。
念のため記しておくと、 haxe のライブラリとして openfl と actuate が指定されている (lime と openfl は、一応は別の存在である) 。
actuate はアニメーション用のライブラリだ。

<assets /> タグでは各種リソース用のディレクトリが指定できる。
ここで使用するファイルまたはディレクトリを登録しておくことで、ソースコード中から openfl.Assets を用いてアクセス可能となる。
PiratePig においては音声ファイルを、うまくプラットフォームに分けて変えているのがわかると思う。

具体的な assets タグの説明については、後で詳しく述べたい。

PiratePig を元にしたプロジェクトファイルの説明は以上になる。
より詳しくは、公式ドキュメントを読むのがよいだろう。

エントリポイントとメインクラスの説明

project.xml でも指定されているとおり、メインクラスは Source/piratepig/PiratePig.hx で定義される
PiratePig クラスだ。
package piratepig;


import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.system.Capabilities;
import flash.Lib;
import openfl.Assets;


class PiratePig extends Sprite {


        private var Background:Bitmap;
        private var Footer:Bitmap;
        private var Game:PiratePigGame;


        public function new () {

                super ();

                initialize ();
                construct ();

                resize (stage.stageWidth, stage.stageHeight);
                stage.addEventListener (Event.RESIZE, stage_onResize);

        }


        private function construct ():Void {

                Footer.smoothing = true;

                addChild (Background);
                addChild (Footer);
                addChild (Game);

        }

        private function initialize ():Void {

                Background = new Bitmap (Assets.getBitmapData ("images/background_tile.png"));
                Footer = new Bitmap (Assets.getBitmapData ("images/center_bottom.png"));
                Game = new PiratePigGame ();

        }


        private function resize (newWidth:Int, newHeight:Int):Void {

                Background.width = newWidth;
                Background.height = newHeight;

                Game.resize (newWidth, newHeight);

                Footer.scaleX = Game.currentScale;
                Footer.scaleY = Game.currentScale;
                Footer.x = newWidth / 2 - Footer.width / 2;
                Footer.y = newHeight - Footer.height;

        }


        private function stage_onResize (event:Event):Void {

                resize (stage.stageWidth, stage.stageHeight);

        }


}

いろいろと書かれている。
PiratePig のゲーム自体に必要なコードが数多く書かれているわけなのだが、必要最小限はどの程度なのだろう?
実は、OpenFL で必要な最小構成は下記に示したコードだけだ。

package piratepig;

import flash.display.Sprite;

class PiratePig extends Sprite {

        public function new () {

                super ();

        }
}

意外……と、いうか、あっけないほど必要なコードが少ないのが見て取れる。
何しろ super() だけだ。
本当にこれだけでいいのか確認したい場合は、なんなら空のプロジェクトを

lime create openfl:project SomeProject

などで作ってみるとすぐにわかる。 本当にこれだけだ。


OpenFL はこれだけでアプリの基本部分がすべて動く。
それもマルチプラットフォームでだ。

基本的なところを抑えたので、次回は「どうやって画像を表示するか」「画像をどうやってアニメーションさせるか」「どうやってマウス入力を取り扱っているか」の3点を、同じく PiratePig を元にしてみていきたい。

2014年3月4日火曜日

Haxe 事始め(1) OpenFL でサンプルを動かしてみるまで

仕事柄様々な技術に触れることが多い。

そんなわけで、突然だけど、 Haxe をやってみようかなと思った。

(1) で終わってしまった RSpec 周りの記事は、来年までに拡充したい。多分。

Haxe って何?


マルチパラダイムな汎用プログラミング言語で、 Haxe をコンパイルすることで C++ や ActionScript, Javascript のコードが生成できる。
パフォーマンスが素晴らしいわけではないけど、工夫次第でどうとでもなりそうな感触があって可愛い子だ。
あと、強めの型づけだったりするのだけど、逆に、バグを起こしにくくしている気がする・・・ので、コードを書いて確かめていきたい。

あまり他のブログとかで触れられていない気がするけれど、もう一つ、個人的に素晴らしいと思った特徴がある。

それは、開発環境の整備が容易だということだ。

例えば、ruby などは Windows 上に開発環境を作ることが絶望的に面倒くさい。と、いうよりも LL の開発環境と Windows との相性はすこぶる悪い。
Java や C++ は開発環境のスタンダードがあるが、そもそも気軽に開発をスタートできるような言語ではない。 VisualStudio 高いし。。。

一方 haxe は自動インストーラが、なんと標準で用意されている。 windows でも、 mac でも。

個人的に Windows8 と Mac OSX で haxe をインストールしたが、インストーラを使えば何も迷うことなくインストールできた。

すこぶる便利な世の中になったと思う。

この記事の目標


さて、この記事では、その Haxe を使った開発キット OpenFL の紹介をしていきたいと思う。


マルチプラットフォームな開発キットとして OpenFL というものがある。

これを使って、何かゲームを作ってみようと思うのだけど、まずはサンプルを動かすまで見ていこう。

ゲームの開発自体は HTML5 でやり、同じコードを様々な環境に移すとどうなるか、ひとつづつ見ていきたい。

OpenFL のインストールまで


これもインストールがものすごく簡単だ。

インストールページを見てほしい

ほら、簡単でしょ(^^ と、思わず顔文字を出したくなるくらいに簡単だ。

OpenFL でサンプルを動かすまでに


  1. Haxe のインストール
  2. lime のインストール
  3. OpenFL のインストール
  4. プラットフォームのセットアップ

と4ステップが必要だが、それぞれ

  1. そのページにある windows って書かれたリンククリックして、ダウンロードできる exe を実行するだけ
  2. そのページに有る2コマンドを cmd.exe か powershell あたりで実行するだけ
  3. そのページに有る1コマンドを cmd.exe か powershell あたりで実行するだけ
  4. そのページに有る1コマンドを cmd.exe か powershell あたりで実行するだけ

で、できるのだ。

嘘だと思うでしょ?

例えば、 lime setup windows をしてみたらどうなったか、スクリーンショットを見てほしい。



そう。必要なら、半自動的に VisualStudio を持ってきてくれるのだ!!!

mac で iOS アプリを作ろうとした時、ないなら XCode のダウンロードページを開いてくれるし、
android アプリを作ろうとした時、みんなが悩む android コマンドや ndk をどこに置くのか、どこから持ってくるのかも、自動的にやってくれる!!

ちなみに著者は、公式ドキュメント通り、 windows 用のセットアップを終わらせた。

Flash と HTML5 のセットアップは特に必要ないので、ここまでの作業で HTML5, Flash そして Windows アプリの開発まで出来るようになったということになる。

サンプルの実行まで


上のステップ 3 まで終われば、サンプルを動かすことまでできる。

lime create openfl:PiratePig

で動かせるサンプルが作れる。
まず、ビルドをするためには lime build TARGET を実行する必要がある。
早速試してみよう。

cd ./PiratePig
lime build html5

著者の環境では、これでエラーが起きた。

Error: Could not find haxelib "actuate", does it need to be installed?

こんなエラーだったので haxelib install actuate してから、もう一度ビルドを実行。今度は成功した。

コマンドラインから実行もできる。

lime run html5

これで実行可能だ!

そして、 html5 を flash に変えることですぐに flash アプリが、 windows に帰ることですぐに windows アプリが作れる。

次回は、 OpenFL の基礎機能を見て行きたいと思う。

それでは。また。

2011年7月5日火曜日

RSpec 簡潔に記述する(1) it ブロックを短く書く!

コード比較


describe User do
  it "should be instance of User" do
    Factory.create(:user).should be_instance_of(User)
  end

  it "should belongs to Guild" do
    Factory.create(:user).guild.should be_instance_of(Guild)
  end

  describe "#add_exp(experience_point)" do
    it "should not raise error" do
      lambda{Factory.create(:user).add_exp(10) }.should_not raise_error
    end
  end

  describe "::get_list()" do
    it "should be instance of Array" do
      User::get_list().should be_instance_of(Array)
    end
  end
end


describe User do
  subject { Factory.create(:user) }
  it { should be_instance_of(User) }
  its(:guild){ should be_instance_of(Guild) }

  describe "#add_exp(experience_point)" do
    subject { lambda{Factory.create(:user).add_exp(10) } }
    it { should_not raise_error }
  end

  describe "::get_list()" do
    subject { User::get_list() }
    it { should be_instance_of(Array) }
  end
end

新旧を比較すると、新しい方は it メソッドが 1 行で書かれており、音読すれば意味が通じる内容と成っているのがわかると思います。(ex, it should not raise error)

それでは、どのようにして簡潔にしていくか、 4 ステップで見ていきましょう。

1. describe ブロック中の subject を定義する

subject メソッドを使い、この describe ブロックで、一体何の spec を書きたいのかを明確に記述します。

subject を定義することで、各 spec 中で subject を参照出来る様になります。

早速書きなおしてみましょう。

describe User do
  subject { Factory.create(:user) } # このブロックは、 User のインスタンスを検証する

  it "should be instance of User" do
    subject.should be_instance_of(User)
  end

  it "should belongs to Guild" do
    subject.guild.should be_instance_of(Guild)
  end

  describe "#add_exp(experience_point)" do
    # このメソッドの実行結果を検証する
    subject { lambda{Factory.create(:user).add_exp(10) } }

    it "should not raise error" do
      subject.should_not raise_error
    end
  end

  describe "::get_list()" do
    # このメソッドの返す値を検証する
    subject { User::get_list() }

    it "should be instance of Array" do
      subject.should be_instance_of(Array)
    end
  end
end

2. subject は省略できる

ぶっちゃけ、subject がなくても、 it メソッドは適当に解釈してくれます。

もとい。もともと、 it メソッドにおいて暗黙のレシーバーが  subject です。

describe User do
  subject { Factory.create(:user) }

  it "should be instance of User" do
    should be_instance_of(User)
  end

  # ここはアトで。
  it "should belongs to Guild" do
    Factory.create(:user).guild.should be_instance_of(Guild)
  end

  describe "#add_exp(experience_point)" do
    subject { lambda{Factory.create(:user).add_exp(10) } }

    it "should not raise error" do
      should_not raise_error
    end
  end

  describe "::get_list()" do
    subject { User::get_list() }

    it "should be instance of Array" do
      should be_instance_of(Array)
    end
  end
end

3. (単純なら) 記述は省略でき (自動生成でき) る。

RSpec では、-fs オプションを付けることで it メソッドのコメントを表示させることが出来ますが、各 spec 中で、出てくる should が 1 つ程度でしたら、 RSpec 自身によって仕様を自動記述出来ます

it メソッドでコメントを省略すると、spec 中から無理やり記述が自動生成されます。

さらに、単純な spec なら 1 行程度なので do - end じゃなくて {} 使っても、あんまり見づらくなりませんので、どんどん省略しちゃいましょう。

逆に言えば、自動生成出来る程度の粒度で 1 つの spec を書くべきです。粒度は細かく。量は多めに!


describe User do
  subject { Factory.create(:user) }
  it { should be_instance_of(User) }
  # ここはアトで。
  it "should belongs to Guild" do
    Factory.create(:user).guild.should be_instance_of(Guild)
  end

  describe "#add_exp(experience_point)" do
    subject { lambda{Factory.create(:user).add_exp(10) } }
    it { should_not raise_error }
  end

  describe "::get_list()" do
    subject { User::get_list() }
    it { should be_instance_of(Array) }
  end
end


4. プロパティや簡単なメソッドとかは its で。

プロパティとか、プロパティっぽく振舞わせるメソッド (正確には、ruby の getter は全部メソッドだけど。。。) は、
it じゃなくて、its を使うと簡潔に書けます。 ただし、あくまでも簡単なプロパティ (の getter) 及びメソッド用です!

subject 自体の spec を書くなら、 it メソッド。subject のプロパティの spec なら its メソッドですな。

書き方は
its(:property_name){ should == true }

見てわかるとおり、

* describe ブロックで定義した subject ブロックの値 と it メソッド内の subject は同じ。
* (describe ブロックで定義した subject ブロックの値).property_name と its メソッド内の subject は同じ。
* property_name メソッドに引数を与えたい? それはムリだから、そういう場合はおとなしく子供の describe ブロックを書こう。

と、なります。


describe User do
  subject { Factory.create(:user) }
  it { should be_instance_of(User) }
  its(:guild){ should be_instance_of(Guild) }

  describe "#add_exp(experience_point)" do
    subject { lambda{Factory.create(:user).add_exp(10) } }
    it { should_not raise_error }
  end

  describe "::get_list()" do
    subject { User::get_list() }
    it { should be_instance_of(Array) }
  end
end
次は「describe と context」「let」について書くことにします。

2011年6月20日月曜日

Rails3 + RSpec2 + Cucumber な環境作り

表題の通り、Rails3 アプリを、RSpec2 + Cucumber を使って作ってみましょう。

rails3 アプリの骨組みづくり

まずは、rails コマンドでアプリの骨組みを作ってしまいます。
この時、オプションを特に指定しないと、デフォルトの設定のままできてしまうので、
各種オプションをつけてやります。

各種オプションってなんでしょう?

rails --help でヘルプを見てみるとこんな風に書かれています。

$rails --help
使い方:
  rails new APP_PATH [options]

オプション:
  -r, [--ruby=PATH]           # Ruby の実行パス
                              # デフォルト: /home/shinsuke/.rvm/rubies/ruby-1.9.x/bin/ruby
  -d, [--database=DATABASE]   # デフォルトで使う DB (オプション: mysql/oracle/postgresql/sqlite3/frontbase/ibm_db)
                              # デフォルト: sqlite3
  -O, [--skip-active-record]  # Active Record 用ファイルをスキップします
  -T, [--skip-test-unit]      # Test::Unit 用ファイルをスキップします
  -J, [--skip-prototype]      # Prototype 用ファイルをスキップします
  -G, [--skip-git]            # Git ignores と keeps をスキップします

ランタイム オプション: 
  -f, [--force]    # すでにファイルが存在している場合、上書きします
  -p, [--pretend]  # コマンドを実行しますが、何も作成しません
  -q, [--quiet]    # rails コマンドのステータスを非表示にします
  -s, [--skip]     # すでにファイルが存在している場合、作成をスキップします

Rails  オプション:
  -v, [--version]  # Rails のバージョンを表示します
  -h, [--help]     # ヘルプメッセージを表示します

概要:
    'rails new' コマンドは新しい Rails アプリケーションの標準的な
    ディレクトリ構成と指定された設定ファイルを作成します。

例:
    rails new ~/Code/Ruby/weblog

    このコマンドは新しい Rails アプリのスケルトンを ~/Code/Ruby/weblog に作成します。
    まずはじめに、自動的に作成された README ファイルを読んでみましょう。

今回は、mysql を使用することにし、また javascript ライブラリは prototype.js ではなく、 jQuery を使うことにします。
さらに、この記事のタイトル通り、test フレームワークは RSpec を用います。
ですので、使用するオプションは、"-d mysql", "-T", "-J" となります。

$rails new specapp -d mysql -T -J
      create
      create  README
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/mailers
      create  app/models
      create  app/views/layouts/application.html.erb
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  doc
      create  doc/README_FOR_APP
      create  lib
      create  lib/tasks
      create  lib/tasks/.gitkeep
      create  log
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  public/images
      create  public/images/rails.png
      create  public/stylesheets
      create  public/stylesheets/.gitkeep
      create  public/javascripts
      create  public/javascripts/.gitkeep
      create  public/javascripts/application.js
      create  script
      create  script/rails
      create  tmp
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  vendor/plugins
      create  vendor/plugins/.gitkeep

こんな感じで、あらかた自動的にアプリが作成されてくれます。

RSpec2 の導入

RSpec2 の公式サイトはコチラ (http://relishapp.com/rspec) です。
このサイトのRSpec Rails 2.6 を読んでいきましょう。

とりあえず、 gem でインストールと書いてありますが、どうせ bundler 経由で gem を管理するので、サクっと Gemfile を編集します。
公式にも書かれているとおり、:development 環境と :test 環境の2つに rspec-rails をインストールすることにしています。

group :development, :test do
  gem 'rspec-rails', '~>2.4'
end

わざわざ :development 環境が指定されているのは、 RSpec を起動するための rake コマンドで、いちいち RAILS_ENV="test" を付けるのを省力化するためです。

Gemfile の編集が終わったら、bundler 経由でインストールを済ませてしまいましょう。

$bundle update

最後に、RSpec 用ファイルの作成コマンドを実行しておしまいです。

$ruby script/rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb

これで、RSpec を動かすのに必要なファイルがそろいました。

Cucumber の導入

Cucumber の公式サイトはコチラ (http://cukes.info/) です。
rails 用のインストールドキュメントは、wiki から飛んだ、github の某ページにあります。

とりあえず、gem でインストールすればよさそうですが、この際、何でもかんでも bundler にやらせましょう
(ちなみに、こうしておけば、大抵の gem の依存関係は解決できるはずです。cucumber install document の "Install new dependenciesもスキップできます。)

Gemfile に 1 行追加します。

group :development, :test do
  gem 'cucumber-rails'
  gem 'rspec-rails', '~>2.4'
end

そしてインストールします。

$bundle update

次に、 RSpec の時と同じく cucumber 用のファイルを rails プロジェクトに追加します。
前もって --help でヘルプを読んでおくと、多分 RSpec を使うためのオプションなどを知っておくことができそうです

$ruby script/rails generate cucumber:install --rspec
      create  config/cucumber.yml
      create  script/cucumber
       chmod  script/cucumber
      create  features/step_definitions
      create  features/step_definitions/web_steps.rb
      create  features/support
      create  features/support/paths.rb
      create  features/support/selectors.rb
      create  features/support/env.rb
       exist  lib/tasks
      create  lib/tasks/cucumber.rake
        gsub  config/database.yml
        gsub  config/database.yml
       force  config/database.yml

これで、ひと通りの導入はおしまいとなります。
それでは、いよいよ実装を行っていきましょう。

2011年6月12日日曜日

とりあえず rails3 の開発環境をつくるまで

おもむろに rvm をインストールします。

次に、ruby をインストールし、使えるようにします。

shinsuke$ rvm install 1.9.2
shinsuke$ rvm use 1.9.2

現状でライブラリは何も入ってません。とりあえず rails をインストールします。

shinsuke$ gem install rails

これで、 rails コマンドや bundler が使えるようになりました。何も考えずに新しく rails アプリを作ります。アプリができたら bundle 経由で各種ライブラリを揃えておしまいです。

shinsuke$ rails new hoge_app -d mysql -T -J
shinsuke$ cd hoge_app
shinsuke$ bundle install

複数バージョンの ruby を使おう! (rvm のインストールと使用方法)

何で使うん?

ruby や php, python はバージョンが変わると地味に挙動が変化します。
ruby では、 1.8 と 1.9 でライブラリの場所が異なったり、後方互換性がなかったりとイロイロ大変です。

そこで登場したのが rvm です。

rvm を使うと、
「今日は ruby 1.9.2 を使おう!」
「やっぱり ruby 1.8 にしよう・・・」
「ruby enterprise edition もいいかな?」
と言った要望を簡単にかなえることができる様になります。

インストール

正確なインストール方法は install documentation (https://rvm.beginrescueend.com/rvm/install/) にあります。

インストール方法が2通りあり、
自分のアカウントで rvm を使う (シングルユーザー用インストール)
システム全体で rvm を使う (マルチユーザー用インストール)
です。

rvm では、シングルユーザー用インストールが推奨されています
rvm の主な目的としては ruby で何かを開発するために、いろいろなバージョンを試したりするために使用すると予測されます。
シングルユーザー用インストールでは、ホームディレクトリ以下に設定ファイルや gem ディレクトリができ、ユーザー毎に違った設定を行えます。
つまり、他のユーザーの環境へは影響を与えないためにシングルユーザー用のインストールが推奨されているのです。

と、いうわけでシングルユーザー用インストールを見てみましょう。

インストール方法は簡単でシェルで

user$ bash < <(curl -s https://rvm.beginrescueend.com/install/rvm)

を実行するだけです。

インストールドキュメントにも書いてありますが、 https://rvm.beginrescueend.com/install/rvm の中身をきちんと理解しておくことが推奨されています。

当たり前ですが、インターネットから取ってきたシェルスクリプトを実行する前には、中身に軽く目を通しておきましょう。

次に、.bash_profile に rvm へのパスを通します。

user$ echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile

を実行し、

user$ source .bash_profile

で .bash_profile を再読込します。

成功していれば

user$ rvm notes

で、 rvm のノートが表示されるはずです。

簡単な使い方

user$ rvm install 1.9.2

で、ruby 1.9.2 がインストールできます。

user$ rvm use 1.9.2

で、インストールした ruby 1.9.2 が使え、

user$ rvm remove 1.9.2

で、ruby 1.9.2 をアンインストールできます。

user$ rvm list known

で、インストール可能な ruby のバージョンが一覧で表示され、

user$ rvm list

で、インストール済みの ruby のバージョンが一覧で表示されます。

gem とか、ruby 製のツールは?

ruby の各種ツールは ~/.rvm/gems/{バージョン}/bin/ に置かれ、 gem は ~/.rvm/gems/{バージョン}/gems におかれます。

つまり、依存関係とか、バージョンの違いとか、その手の面倒くさくて死にそうな作業から一挙に解放されます。ヒャホーイ

user$ rvm use 1.9.2
user$ rvm use 1.8.7

などで、 ruby のバージョンを切り替えた後、

user$ gem list --local
user$ rake --version
user$ which gem

などを実行してみると、見事にバージョンによって中身が全部切り替わっていることがわかるかと思います。