Windowsでrubyをはじめよう

# 前書き
 普段、Windowsでrubyを使っているのだけど、他のruby未経験者用にも使ってもらう必要が出てきたので、その説明資料として本稿を記す。
 本稿の特徴は下記。

1. Windows版rubyの情報である。
2. 2019年1月に書いている。
3. 会社のイントラネット内での使用を想定して、proxy設定の情報を載せている。
4. 複数バージョンのrubyの共存使用を前提としている。
5. gem(拡張ライブラリ)管理のためのbundler, 単体テストのためのrspec, TDDやリファクタリングのためのguardについても、非常に簡単な例を載せている。

...ということで、以下、本文。

# rubyとは
 rubyはMatzこと まつもとゆきひろ氏 が開発したプログラミング言語。[Wikipediaへのリンク](https://ja.wikipedia.org/wiki/Ruby)。

### 言語として
ワンライナーでも使えるし、オブジェクト指向を使った本格的なシステムも組める。何より、"Enjoy programming"という設計思想で作られていて、プログラムを組んでいてストレスを感じることが少ない。

### gem
rubyの拡張ライブラリ。メールを出すとか、httpで通信するとか、さまざまな機能を「ライブラリ」として提供してくれる。

たいていのgemはMatzさん以外のrubyの開発者が作ったものである。

配布されているruby本体にもある程度のgemが入っている。標準で入っていないgemはネットからダウンロード/インストールして使う。

### 実装

Matzさんが開発するいわゆる[MRI](https://ja.wikipedia.org/wiki/Ruby_MRI)の他、javaで動く[JRuby](https://www.jruby.org/) や.NET Frameworkで動く[IronRuby](http://ironruby.net/)等がある。

Windows版の[ActiveScriptRuby](https://www.artonx.org/data/asr/)や[RubyInstaller](https://rubyinstaller.org/)はMRIの一種。

本稿では[RubyInstaller](https://rubyinstaller.org/)を扱っている。

### バージョン
Matzさんが開発するいわゆる[MRI](https://ja.wikipedia.org/wiki/Ruby_MRI)は2018年12月に2.6.0がリリースされた。Windows版の[RubyInstaller](https://rubyinstaller.org/)も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](https://rubyinstaller.org/)からダウンロード・インストールする。

まずは[Downloadページ](https://rubyinstaller.org/downloads/)からインストールしたいバージョンをダウンロードする。この原稿を書いている2019-01-12現在、2.6.0は新しすぎるということでこのWeb上では推奨されていないが、新バージョンは毎年出るのでここでは例として2.6.0-1を使っている。
![rubyinstallerweb.png](https://qiita-image-store.s3.amazonaws.com/0/21992/f965706d-fdf6-4fab-ad89-d3f22c587aed.png)

最近のバージョンは"WITH DEVKIT"と"WITHOUT DEVKIT"があるが、ここでは必ず"WITH DEVKIT"をダウンロードする。

"Devkit"というのは要するにCコンパイラ等の開発ツールで、一部のgemではインストール時にCコンパイラを使ったりするので、Devkitがインストールされていないとそういうgemをインストールできない。筆者が使っているgemで言うと[ruby-odbc](http://www.ch-werner.de/rubyodbc/)がDevkitを使っているし、本稿でもこの後出てくるwdmというgemでDevKitを使っている。*nix環境ではCコンパイラは普通入っているが、Windowsでは入っていないので、ruby本体とセットになっているというわけ。

x64とx86の違いは64bit版か32bit版かの違いである。

ダウンロードしたら管理者権限でそのファイルを実行する。ちなみに管理者権限でなくともインストーラは起動するが、システム環境変数の設定に失敗する等不具合が出るようだ。

ライセンス条項を受け入れて
![rubywininstall-1.png](https://qiita-image-store.s3.amazonaws.com/0/21992/b6d8fe04-eed2-6c1a-2ab3-9b7c194272d3.png)

インストール先を指定。
![rubywininstall2.png](https://qiita-image-store.s3.amazonaws.com/0/21992/47eb0ffb-9bb7-95e5-3611-895258a0c608.png)


インストール先はデフォルトでは`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ボタンをクリックする。

![rubywininstall3.png](https://qiita-image-store.s3.amazonaws.com/0/21992/cd064489-99fd-e15a-b954-065a8ae79154.png)

↑このダイアログは以前は出ていなかったような気がするが、DEVKIT(MSYS2 Development toolchain)をインストールしない場合はMSYS2のチェックをここで外せとのこと。今回DEVKITはインストールするのでそのままNextボタンをクリックする。

![rubywininstall4.png](https://qiita-image-store.s3.amazonaws.com/0/21992/906d8c63-9ecb-22ad-69bb-deec6ff2c07d.png)

![rubywininstall5.png](https://qiita-image-store.s3.amazonaws.com/0/21992/9babed10-fc8b-23e6-f048-5c6e041fb61d.png)

そうすると、↑のようにインストールが始まり...

![rubywininstall6.png](https://qiita-image-store.s3.amazonaws.com/0/21992/ed72aa77-fdc1-1828-944d-fef703eaf6a4.png)

終わったら上記のようなダイアログが出る。DEVKIT(MSYS2)のインストールについてしつこくチェックボックスが出るが、チェックを入れたままFinishボタンをクリックする。

![msys2install1.png](https://qiita-image-store.s3.amazonaws.com/0/21992/c0309f9f-2824-aa5a-589d-4d87ed401263.png)

コマンドプロンプトが起動して、Devkit(MSYS2)のインストール画面になる。1,2,3と選択項目があるが`If unsure press ENTER`ということなので何も入れずに[ENTER]キーを押す。

![msys2install2.png](https://qiita-image-store.s3.amazonaws.com/0/21992/16188577-20f6-5304-dfbe-87a65ca033c1.png)

そうするとMSYS2のセットアップが始まる。

![msys2install3.png](https://qiita-image-store.s3.amazonaws.com/0/21992/42ca62ce-7e3b-2def-bce3-b6c0a930c266.png)

一通り終わるとまた`Which components shall be installed? If unsure press ENTER`と言ってきて入力待ちになるのでまた[ENTER]を押す。場合によってはここでMSYS2のアップデートが始まることもあるし、何もせずにコマンドプロンプトが閉じることもある。ともあれ、コマンドプロンプトが自動的に閉じるまで"press ENTER"を繰り返す。

### ruby本体のバージョン切り替えツール uru

下記Qiita記事を参考に設定。ただしuruの最近のバージョンは.zipではなく.7zで圧縮してあるので、解凍するためには[7-Zip](https://sevenzip.osdn.jp/)等のツールが別途必要。

[Windowsにuruを入れてrubyのバージョン管理をする - Qiita](https://qiita.com/shwld/items/0e9f143575a985a6585b)


### インストール後の確認

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

```

### インストール後のフォルダ構成

![afterinstall.png](https://qiita-image-store.s3.amazonaws.com/0/21992/828aeea1-1956-6618-1631-9ffc9a3ced18.png)

インストール後の`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](https://www.msys2.org/)は、もともとはWindows上にlinuxの開発環境全般を再現するためのソフトウェアで、ここにはrubyでは使わないものも含めて一式入っているので結構ディスクを消費している(msys64以下で830MB)。

だいたい1バージョン当たり、MSYS2=DevKit含めて1GB弱というところで、いまどきはこのくらいのディスクは食うのかなという感じ。

頑張って同じMSYS2を複数バージョンのrubyから使うという設定も可能かもしれないが、これはシンプルな構造ではないのでお勧めできない。

# 開発環境のセットアップ

ここまでの作業でrubyは使えるようになっているが、もう少しだけ、開発環境を整える。

### テキストエディタ

ソースコードを編集するテキストエディタは、各人が好みのものを使えば良いと思うが、もし何を使えば良いか判らないということであればここでは[Visual Studio Code](https://code.visualstudio.com/) (以下 vscode)をお勧めする。

(vscodeの設定とか、便利なプラグインとか、いろいろあるのだけど、本稿では省略)

### 開発環境の作成と確認

#### bundle initとbundle install

開発環境の作成と確認のため、以下で"DevTest"というフォルダを作ってその中で作業する。このフォルダの中で簡単なrubyのコードとそのテストコードを書いてみる。

```
md DevTest
cd DevTest
```

1. bundlerを使ってgemを管理するため、Gemfileというテキストファイルを作成する。
コマンドラインから

```
bundle init
```

を実行するとbundlerが初期化されたGemfileを作ってくれるので、エディタでその内容を編集する。以下のように`gem 'guard'`以下 `gem`で始まる行を4つ追加する。それぞれ何をするgemかの説明はここでは省略する。

また、`gem 'guard-rspec', require: false`とか`gem 'wdm', '>= 0.1.0'`とか、行の後半の意味が判らないかもしれないが、ここではこのままコピペしてください(bundlerについての技術情報を探せば詳しい説明があると思う)。

``` ruby:Gemfile
# 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環境を作成できる、という仕組みである。

```ruby:Gemfile.lock
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`の内容は下記の通り。

```ruby:lib\dev_test.rb
class DevTest
    def return_abc
        'abc'
    end
end
```

```ruby:spec\dev_test_spec.rb
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のターミナルウィンドウが出るので、そこで上記コマンドを入力する。

![vscode_terminal.png](https://qiita-image-store.s3.amazonaws.com/0/21992/4d0e4728-ced7-76a5-f2e1-d3989c1aa034.png)


この状態で、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
```

![vscode_terminal2.png](https://qiita-image-store.s3.amazonaws.com/0/21992/863b3baf-bf7d-5219-5a92-e5414f8ac754.png)


この例では「テストのためのテスト」なのでピンと来ないかもしれないが、実際の開発では大変有用な仕組みになる。


# 参考
- [Windowsにuruを入れてrubyのバージョン管理をする - Qiita](https://qiita.com/shwld/items/0e9f143575a985a6585b)
- [橋本商会 » Ruby書くならBundler使え](http://shokai.org/blog/archives/7262)
- [Guardでrspecのテストを自動化する - SHOYAN BLOG](http://48n.jp/blog/2016/05/24/introduce-guard-gem-and-guard-rspec/)