mruby-yeahとmruby-cliで小さいWebアプリのhello world

自動翻訳感のあるタイトルですが間違ってはいないのでこのまま行きます。

mruby-yeahとmruby-cliを使って単一実行ファイルで動くWebアプリのサンプルを作ります。

# 前提

* ubuntu
* docker, docker-compose: コンパイルするのに必要です。導入手順は割愛。

* mruby-cli 0.0.4: 単一実行ファイルにコンパイルされるcliツールの実装を行うためのライブラリ
  * クロスコンパイル対応の設定ファイルやプロジェクト用のディレクトリを生成してくれる
* mruby-yeah: mrubyでWebアプリを実装するためのライブラリ

# mruby-cliで雛形を作る

まずmruby-cliの実行ファイルを落としてきてパスを通し実行できる状態にします。

次に開発を行うためのディレクトリと関連ファイルをmruby-cliで生成します。

```
mruby-cli --set-up sample
cd sample
```

一度コンパイルして実行してみて`Hello World`が表示されれば成功です。

```
sudo docker-compose up --build
sudo docker-compose run compile
sudo ./mruby/build/host/bin/sample
```

# mruby-cliで生成したファイルのmrubyバージョン指定を変更する

大筋で生成されるファイルに問題はないのですが、
mruby-cli バージョン0.0.4が生成するファイルはmruby1.2でビルドを行っており、
mruby-yeahが動作するのはmruby1.4のようなので一部ファイルを修正します。

一度コンパイルしていると既に1.2のmrubyがダウンロードされているので、
sampleディレクトリ直下のmrubyディレクトリも削除しておいてください。

```
vim Rakefile
```

```
 require 'fileutils'

-MRUBY_VERSION="1.2.0"
+MRUBY_VERSION="1.4.0"

 file :mruby do
   #sh "git clone --depth=1 https://github.com/mruby/mruby"
-  sh "curl -L --fail --retry 3 --retry-delay 1 https://github.com/mruby/mruby/archive/1.2.0.tar.gz -s -o - | tar zxf -"
-  FileUtils.mv("mruby-1.2.0", "mruby")
+  sh "curl -L --fail --retry 3 --retry-delay 1 https://github.com/mruby/mruby/archive/#{MRUBY_VERSION}.tar.gz -s -o - | tar zxf -"
+  FileUtils.mv("mruby-#{MRUBY_VERSION}", "mruby")
 end

 APP_NAME=ENV["APP_NAME"] || "sample"
```

```
sudo rm -rf mruby
```

# windows向けのコンパイルはコメントアウトする

mruby-cliの生成する雛形ではwindows向けのクロスコンパイルも含まれます。
mruby-yeahを含めた場合だとコンパイルが通らなかったのでWindows向けのクロスコンパイルに関する記述をコメントアウトします。

デフォルトでは他にmac向け、linuxの32bit, 64bit向けのビルドも行われます。
コンパイル時間に影響するはずなので他にも不要な物は外してしまっても良いでしょう。

```
vim build_config.rb
```

```
--- build_config.rb.before_rm_windows	2018-03-31 16:44:13.485515441 +0900
+++ build_config.rb	2018-03-31 16:47:28.389557167 +0900
@@ -61,34 +61,34 @@
   gem_config(conf)
 end
 
-MRuby::CrossBuild.new('x86_64-w64-mingw32') do |conf|
-  toolchain :gcc
-
-  [conf.cc, conf.linker].each do |cc|
-    cc.command = 'x86_64-w64-mingw32-gcc'
-  end
-  conf.cxx.command      = 'x86_64-w64-mingw32-cpp'
-  conf.archiver.command = 'x86_64-w64-mingw32-gcc-ar'
-  conf.exts.executable  = ".exe"
-
-  conf.build_target     = 'x86_64-pc-linux-gnu'
-  conf.host_target      = 'x86_64-w64-mingw32'
-
-  gem_config(conf)
-end
-
-MRuby::CrossBuild.new('i686-w64-mingw32') do |conf|
-  toolchain :gcc
-
-  [conf.cc, conf.linker].each do |cc|
-    cc.command = 'i686-w64-mingw32-gcc'
-  end
-  conf.cxx.command      = 'i686-w64-mingw32-cpp'
-  conf.archiver.command = 'i686-w64-mingw32-gcc-ar'
-  conf.exts.executable  = ".exe"
-
-  conf.build_target     = 'i686-pc-linux-gnu'
-  conf.host_target      = 'i686-w64-mingw32'
-
-  gem_config(conf)
-end
+# MRuby::CrossBuild.new('x86_64-w64-mingw32') do |conf|
...中略
+# end
+
+# MRuby::CrossBuild.new('i686-w64-mingw32') do |conf|
...中略
+# end
```

# webアプリとしてのコードを書く

まずmruby-yeahをmruby-cliが生成した `mrbgem.rake` に追記します。
これにより次のコンパイル時にmruby-yeahも取り込んだ実行ファイルが生成されます。

```ruby
MRuby::Gem::Specification.new('sample') do |spec|
  spec.license = 'MIT'
  spec.author  = 'MRuby Developer'
  spec.summary = 'sample'
  spec.bins    = ['sample']

  spec.add_dependency 'mruby-print', :core => 'mruby-print'
  spec.add_dependency 'mruby-mtest', :mgem => 'mruby-mtest'
  spec.add_dependency 'mruby-yeah' # この行を追加
end
```

mruby-cliが生成した`mrblib/sample.rb`ファイルにmruby-yeah向けのコードを書きます。
getアクセスされたら `Hello web app!` とレスポンスを返すようにします。

```
vim ./mrblib/sample.rb
```

```ruby
# 実装の例

# '-p 3000' または '--port 3000'
# オプションでポート番号を指定可能になります。
opt(:port) { |p| set(port: p) }

# curl localhost:<port>/test
# => Hello web app!
get('/test') do
  'Hello web app!'
end
```

# 実行

mruby1.4とmruby-yeahの取得、sampleの再コンパイルをした上で
HTTPリクエストをした際の動作が期待通りか見てみます。

curlでHTTPアクセスを飛ばして `Hello web app!` が表示されれば成功です。

```
sudo docker-compose run compile
export SHELF_ENV=development # 何かしら指定しないとエラー。デフォルトでdevelopにしてくれたりはしない模様
sudo chmod +r -R mruby
./mruby/build/host/bin/sample --port 3000

# 別のターミナルで
curl http://localhost:3000/test

```