Bash on WindowsでRails開発

## 前書き

予め言っておきますが、僕の所属している会社は、サーバサイドエンジニアには最新のMacBookProを配布してますので、タイトルにあるような闇に突っ込む真似をさせたりはしていません。本記事は個人的に趣味でやってみた記録です。

## ついにきた

- Windows10 Anniversary Update
    - Bash on WindowsはまだBetaだけど、Updateに含まれており、設定で有効にできる
- Docker for Windows/Mac
    - VirtualBox上のCoreOSを用意しなくても、Windows/Mac上で直接Dockerが動く

## Railsぐらいは動くんじゃね？動いて欲しいｗ

- bashが動くなら、rbenvが動くはず
- apt-getで適切にライブラリ入れればrubyインストールできるはず
- DBとか、周辺ミドルウェアはDockerに任せとけ
- あとはnative extensionを含むgem次第

## やってみた

Ruby 2.3.1
Rails 5.0.0

な感じのRailsアプリケーションを動かすのをゴールにして、環境構築からやってみる

- rbenv
    - 普通にubuntuにインストールする手順で行ける
- rbenv経由のrubyインストール
    - 問題なし
- bundler(on rbenv)
    - なぜか僕の環境では、bash起動時に `umask 022` を通ってなかった
    - それに気づかずここまで来てしまったため、 `~/.rbenv` 下に、permission 777のディレクトリが大量にできてしまった
    - bundlerは777のディレクトリを拒否するので、コケた
    - `chmod -R go-w ~/.rbenv` 実行と、.bashrcに `umask 022` 追加した
    - ↑で問題なく動いた
- Docker
    - 問題なし
    - インストール時に再起動を要求されたので、rubyまわりの環境構築と同時にやってる場合は注意
- native extension インストール
    - 問題なし
    - Linuxでもたまにハマるnokogiriも一発でインストール成功した
- rails実行
    - ハマった。後述。

## Rails起動でハマった

こんなの出た

```
rails aborted!
Errno::EINVAL: Invalid argument - Failed to watch "/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/activesupport-5.0.0/lib/active_support/locale": the given event mask contains no legal events; or fd is not an inotify file descriptor.
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rb-inotify-0.9.7/lib/rb-inotify/watcher.rb:74:in `initialize'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rb-inotify-0.9.7/lib/rb-inotify/notifier.rb:190:in `new'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rb-inotify-0.9.7/lib/rb-inotify/notifier.rb:190:in `watch'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rb-inotify-0.9.7/lib/rb-inotify/notifier.rb:204:in `watch'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/adapter/linux.rb:32:in `_configure'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/adapter/base.rb:45:in `block in configure'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/adapter/base.rb:40:in `each'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/adapter/base.rb:40:in `configure'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/adapter/base.rb:63:in `start'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/listener.rb:68:in `block in <class:Listener>'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/fsm.rb:121:in `instance_eval'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/fsm.rb:121:in `call'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/fsm.rb:91:in `transition_with_callbacks!'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/fsm.rb:57:in `transition'
/home/nishioka/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/listen-3.1.5/lib/listen/listener.rb:91:in `start'
```

### 何が起きたか

デフォルト設定で、 `RAILS_ENV=development` でrailsを起動すると、 `file_watcher` ってのがセットされる。 `rails server` 時に、ソースコード書き換えたら勝手に反映されるのをトリガーするやつ。デフォルト設定は `config/environments/development.rb` に書いてある。

```rb
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
```

で、こいつは、
`rb-inotify` -> `ffi` 経由で、擬似（？）native extensionになっていて、nativeのinotifyを使う。

https://github.com/nex3/rb-inotify/blob/v0.9.7/lib/rb-inotify/native.rb

しかし、残念ながら、Bash on WindowsはFilesystem watchに対応していない。

https://github.com/Microsoft/BashOnWindows/issues/216

### 回避

あんまりうれしくないけど、 `config/environments/development.rb` で、inotifyを使わないように設定してやることができる。

```rb
config.file_watcher = ActiveSupport::FileUpdateChecker
```

これで動いた！

## 余談

これはBash on Windows関係ない話だけど、一応。

mysql clientはhostを `localhost` と設定すると、Unix Socketを見に行く。
が、Docker上にmysql serverを立てていると、TCPしか空いてないので、コケる。
`127.0.0.1` を設定するとTCPを使うようになる。