前書き
普段、Windowsでrubyを使っているのだけど、他のruby未経験者用にも使ってもらう必要が出てきたので、その説明資料として本稿を記す。
本稿の特徴は下記。
- Windows版rubyの情報である。
- 2019年1月に書いている。
- 会社のイントラネット内での使用を想定して、proxy設定の情報を載せている。
- 複数バージョンのrubyの共存使用を前提としている。
- gem(拡張ライブラリ)管理のためのbundler, 単体テストのためのrspec, TDDやリファクタリングのためのguardについても、非常に簡単な例を載せている。
...ということで、以下、本文。
rubyとは
rubyはMatzこと まつもとゆきひろ氏 が開発したプログラミング言語。Wikipediaへのリンク。
言語として
ワンライナーでも使えるし、オブジェクト指向を使った本格的なシステムも組める。何より、"Enjoy programming"という設計思想で作られていて、プログラムを組んでいてストレスを感じることが少ない。
gem
rubyの拡張ライブラリ。メールを出すとか、httpで通信するとか、さまざまな機能を「ライブラリ」として提供してくれる。
たいていのgemはMatzさん以外のrubyの開発者が作ったものである。
配布されているruby本体にもある程度のgemが入っている。標準で入っていないgemはネットからダウンロード/インストールして使う。
実装
Matzさんが開発するいわゆるMRIの他、javaで動くJRuby や.NET Frameworkで動くIronRuby等がある。
Windows版のActiveScriptRubyやRubyInstallerはMRIの一種。
本稿ではRubyInstallerを扱っている。
バージョン
Matzさんが開発するいわゆるMRIは2018年12月に2.6.0がリリースされた。Windows版のRubyInstallerも2019-01-12時点で2.6.0が出ているようだ。
新規にインストールする場合は、深く考えず最新版を入れれば良い。他の言語みたいに2.0系と3.0系が併用されているという状況はない。
ただし本番環境で本格的に使い始めたら、その後で新しいバージョンが出たからといって、テストもせずに即座に差し替えるというわけにはいかなくなる。一方で、新しいバージョンには追随していかないと、古いバージョンはいずれサポート対象外となってセキュリティパッチ等も出なくなる。
つまり、開発環境では現行のバージョンで本番用の開発をする傍らで新バージョンのテストも行う必要があるので、複数バージョンを併用する必要がある。そのための仕組みとして、macやlinuxではrbenvというツールを使うのが一般的なようだがWindowsにはそれがないので本稿では後述するuruというツールを使う。
また、ruby本体同様に、gemにもバージョンがあって、ruby本体と同様の課題がある。さらにgemの場合は、実行環境ごとにインターネット経由でインストールするので、極端なことを言えば昨日セットアップしたサーバと今日セットアップしたサーバでバージョンが異なる状況が発生することもある。これを解決するため、後述するbundlerというツールを使う。
Windows環境でインストール
環境変数の設定を確認
のちのち、必要なgemをインターネット経由でインストールすることになる。自宅で個人がネットにつなぐ場合は特に問題ないが、会社のイントラネットからgemをインストールする場合にはイントラネットとインターネットを隔てる「ファイアウォール」を超えるためのプロキシサーバの設定が必要になる。
この設定は環境変数http_proxyで行う。プロクシサーバのアドレスが192.0.2.1でポートが80だった場合は
set http_proxy=http://192.0.2.1:80
と設定しておく。
また認証つきproxyの場合は
set http_proxy=http://user:password@192.0.2.1:80
と設定する。
この環境変数はgemのインストールだけではなく、ruby本体と一緒にインストールするDevkit(説明は次節)のインストールでも使うので必ず最初に実行しておく。
ruby本体とDevkitのインストール
ここではWindows用として、RubyInstaller for WindowsのWebからダウンロード・インストールする。
まずはDownloadページからインストールしたいバージョンをダウンロードする。この原稿を書いている2019-01-12現在、2.6.0は新しすぎるということでこのWeb上では推奨されていないが、新バージョンは毎年出るのでここでは例として2.6.0-1を使っている。
最近のバージョンは"WITH DEVKIT"と"WITHOUT DEVKIT"があるが、ここでは必ず"WITH DEVKIT"をダウンロードする。
"Devkit"というのは要するにCコンパイラ等の開発ツールで、一部のgemではインストール時にCコンパイラを使ったりするので、Devkitがインストールされていないとそういうgemをインストールできない。筆者が使っているgemで言うとruby-odbcがDevkitを使っているし、本稿でもこの後出てくるwdmというgemでDevKitを使っている。*nix環境ではCコンパイラは普通入っているが、Windowsでは入っていないので、ruby本体とセットになっているというわけ。
x64とx86の違いは64bit版か32bit版かの違いである。
ダウンロードしたら管理者権限でそのファイルを実行する。ちなみに管理者権限でなくともインストーラは起動するが、システム環境変数の設定に失敗する等不具合が出るようだ。
インストール先はデフォルトではC:\Ruby26-x64
等C:\の直下で出るが、来年になればruby 2.7をたぶん入れるだろうと考えて、上記のような指定にしている。C:\Rubyの下にいろいろなバージョンのrubyを入れるイメージである。
C:\Ruby
├─Ruby24-x64
├─Ruby25-x64
└─Ruby26-x64
インストール先の指定の下にあるオプションは
-
Add Ruby executables to your PATH
は、筆者はチェックを入れていない。複数バージョンのrubyを使っていて、「デフォルト」のバージョンへのPATHは別途手動で設定している。 -
Associate .rb and .rbw files with the Ruby installation
にはチェックを入れない。エクスプローラから.rbファイルなどをダブルクリックしてrubyを実行してもうれしくない。 -
Use UTF-8 as default external encoding
は...以前はチェックを入れなかったがそろそろ入れるべきかも。まあここでは入れない。
ということで、各項目を設定したらInstallボタンをクリックする。
↑このダイアログは以前は出ていなかったような気がするが、DEVKIT(MSYS2 Development toolchain)をインストールしない場合はMSYS2のチェックをここで外せとのこと。今回DEVKITはインストールするのでそのままNextボタンをクリックする。
そうすると、↑のようにインストールが始まり...
終わったら上記のようなダイアログが出る。DEVKIT(MSYS2)のインストールについてしつこくチェックボックスが出るが、チェックを入れたままFinishボタンをクリックする。
コマンドプロンプトが起動して、Devkit(MSYS2)のインストール画面になる。1,2,3と選択項目があるがIf unsure press ENTER
ということなので何も入れずに[ENTER]キーを押す。
そうするとMSYS2のセットアップが始まる。
一通り終わるとまたWhich components shall be installed? If unsure press ENTER
と言ってきて入力待ちになるのでまた[ENTER]を押す。場合によってはここでMSYS2のアップデートが始まることもあるし、何もせずにコマンドプロンプトが閉じることもある。ともあれ、コマンドプロンプトが自動的に閉じるまで"press ENTER"を繰り返す。
ruby本体のバージョン切り替えツール uru
下記Qiita記事を参考に設定。ただしuruの最近のバージョンは.zipではなく.7zで圧縮してあるので、解凍するためには7-Zip等のツールが別途必要。
Windowsにuruを入れてrubyのバージョン管理をする - Qiita
インストール後の確認
uruをインストールしたら早速rubyを登録する。
C:\Users\kono>uru admin add C:\Ruby\Ruby26-x64\bin
---> Registered ruby at `C:\Ruby\Ruby26-x64\bin` as `260p0`
rubyが呼び出せることを確認。
C:\Users\kono>uru 260
---> now using ruby 2.6.0-p0 tagged as `260p0`
C:\Users\kono>ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x64-mingw32]
bundlerというgemをインストールして、gemがインストールできることを確認する。bundlerのインストールは下図のようにgemコマンドを使う。
C:\Users\kono>gem install bundler
Fetching bundler-2.0.1.gem
Successfully installed bundler-2.0.1
Parsing documentation for bundler-2.0.1
Installing ri documentation for bundler-2.0.1
Done installing documentation for bundler after 15 seconds
1 gem installed
インストール後のフォルダ構成
インストール後のC:\Ruby\Ruby26-x64
フォルダ構成は上の通り。
binに本体のruby.exeが入っている。
Devkitはmsys64
以下にインストールされ、gemはlib
以下にインストールされる。
複数バージョンが混在する場合、これらmsys64フォルダやlibフォルダの構成は下図のようになる。
C:\Ruby
├─Ruby24-x64
| ├─bin
| ├─msys64
| └─lib
├─Ruby25-x64
| ├─bin
| ├─msys64
| └─lib
└─Ruby26-x64
├─bin
├─msys64
└─lib
つまり、各バージョン毎にDevkitとgemが分かれている。
msys64フォルダに入っているMSYS2は、もともとはWindows上にlinuxの開発環境全般を再現するためのソフトウェアで、ここにはrubyでは使わないものも含めて一式入っているので結構ディスクを消費している(msys64以下で830MB)。
だいたい1バージョン当たり、MSYS2=DevKit含めて1GB弱というところで、いまどきはこのくらいのディスクは食うのかなという感じ。
頑張って同じMSYS2を複数バージョンのrubyから使うという設定も可能かもしれないが、これはシンプルな構造ではないのでお勧めできない。
開発環境のセットアップ
ここまでの作業でrubyは使えるようになっているが、もう少しだけ、開発環境を整える。
テキストエディタ
ソースコードを編集するテキストエディタは、各人が好みのものを使えば良いと思うが、もし何を使えば良いか判らないということであればここではVisual Studio Code (以下 vscode)をお勧めする。
(vscodeの設定とか、便利なプラグインとか、いろいろあるのだけど、本稿では省略)
開発環境の作成と確認
bundle initとbundle install
開発環境の作成と確認のため、以下で"DevTest"というフォルダを作ってその中で作業する。このフォルダの中で簡単なrubyのコードとそのテストコードを書いてみる。
md DevTest
cd DevTest
- bundlerを使ってgemを管理するため、Gemfileというテキストファイルを作成する。
コマンドラインから
bundle init
を実行するとbundlerが初期化されたGemfileを作ってくれるので、エディタでその内容を編集する。以下のようにgem 'guard'
以下 gem
で始まる行を4つ追加する。それぞれ何をするgemかの説明はここでは省略する。
また、gem 'guard-rspec', require: false
とかgem 'wdm', '>= 0.1.0'
とか、行の後半の意味が判らないかもしれないが、ここではこのままコピペしてください(bundlerについての技術情報を探せば詳しい説明があると思う)。
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem 'guard'
gem 'guard-rspec', require: false
gem 'wdm', '>= 0.1.0'
gem 'win32console'
追加したらGemfileを保存して、コマンドプロンプトから
bundle install
というコマンドを実行する。
これらの操作により、Gemfileに書いたguard
, guard-rspec
, wdm
, win32console
のgemと、これらのgemが依存するgemが自動的にインストールされる。
bundle install
が終わったら、Gemfileの他にGemfile.lockというファイルが出来ていて、中にはインストールされたgemとそのバージョンが書き込まれている。このGemfile.lockを他のサーバなどにコピーしてbundlerを使えば、今の環境とそっくり同じgem環境を作成できる、という仕組みである。
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.2)
diff-lcs (1.3)
ffi (1.10.0-x64-mingw32)
formatador (0.2.5)
guard (2.15.0)
formatador (>= 0.2.4)
(...以下略)
つまり、開発環境Gemfile.lockは開発環境のコピー/バックアップに使えるという意味で、実はGemfileよりも重要なファイルである。
本稿でGemfileに書いたgemは主に単体テストで使う、開発時用のgemだが、実際の本番処理で使うgemについても同様の方法で管理できる。
rspec --initとguard init
続いて単体テストの準備。rubyの単体テストツールは何種類かあるがここではrspecというツールを使う。コマンドラインから
bundle exec rspec --init
を実行する。
C:\Users\kono\DevTest>bundle exec rspec --init
create .rspec
create spec/spec_helper.rb
このように.rspec
とspec/spec_helpter.rb
という2つのファイルが作られる。
続いて、ソースコードの変更を監視するツールGuardを準備する。コマンドラインから
bundle exec guard init
を実行する。
C:\Users\kono\DevTest>bundle exec guard init
15:11:25 - INFO - Writing new Guardfile to C:/Users/kono/DevTest/Guardfile
15:11:25 - INFO - rspec guard added to Guardfile, feel free to edit it
このように、Guardfile
というファイルが作られる。
.rspec
, spec/spec_helper.rb
, Guardfile
の各ファイルは、ここでは生成されたものをそのまま使う。
ソースコードdev_test.rbとテストコードdev_test_spec.rb
最後のステップとして、
- libフォルダを作って、ソースコード
lib\dev_test.rb
を作成する。 - specフォルダの下に、単体テストのコード
spec\dev_test_spec.rb
を作成する。 -
dev_test.rb
,dev_test_spec.rb
の内容は下記の通り。
class DevTest
def return_abc
'abc'
end
end
require_relative '../lib/dev_test'
RSpec.describe 'DevTest behavor' do
let(:target) {DevTest.new}
it 'should do return "abc"' do
expect(target.return_abc).to eq 'abc'
end
end
以上で単体テストの準備はととのった。
rspecコマンドとguardコマンドの確認。
最後にrspecを使った単体テストと、ソースコード変更の都度rspecで確認するguardコマンドを確認する。
まずはコマンドラインからrspecを実行。下記のようにbundle exec rspec
とコマンドを入力する。
C:\Users\kono\DevTest>bundle exec rspec
.
Finished in 0.01637 seconds (files took 0.33089 seconds to load)
1 example, 0 failures
↑単体テストが一つ、成功する。
次に下記のようにbundle exec guard
とコマンドを入力する。
C:\Users\kono\DevTest> bundle exec guard
15:41:45 - INFO - Guard::RSpec is running
15:41:45 - INFO - Guard is now watching at 'C:/Users/kono/DevTest'
[1] guard(main)>
vscodeを使っているのであれば、[Terminal]→[New Terminal]で下図のようにPowershellのターミナルウィンドウが出るので、そこで上記コマンドを入力する。
この状態で、Guardはソースコード/テストコードの変更を監視している状態である。試しにreturn_abcメソッドが返す文字列を'abc'から'abcd'に変更して、上書き保存してみると、ファイル変更を検知して自動的にテストが走り、失敗する。
16:45:47 - INFO - Running: spec/dev_test_spec.rb
F
Failures:
1) DevTest behavor should do return "abc"
Failure/Error: expect(target.return_abc).to eq 'abc'
expected: "abc"
got: "abcd"
(compared using ==)
# ./spec/dev_test_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.04383 seconds (files took 0.35617 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/dev_test_spec.rb:6 # DevTest behavor should do return "abc"
return_abcメソッドの文字列を'abc'に戻して上書き保存すると、自動的にテストが走って今度は成功する。
16:48:49 - INFO - Running: spec/dev_test_spec.rb
.
Finished in 0.00596 seconds (files took 0.35307 seconds to load)1 example, 0 failures
この例では「テストのためのテスト」なのでピンと来ないかもしれないが、実際の開発では大変有用な仕組みになる。