OpalでElectronのアプリをつくる(その1)

この記事は[Opal Advent Calendar 2016](http://qiita.com/advent-calendar/2016/opal)の14日目の投稿として書いています。

またまた遅刻です。OpalでElectronアプリをつくろうとしたのですが、なかなか苦労してしまいました。
残念ながら今回の記事だけで完結しなそうです。

<font color='red'>この記事には間違いがありました。詳しくは[15日目の記事](http://qiita.com/youchan@github/items/9a2b0b9e5c511457773f)にゆずりますが、[ここ](#here)から先を読むときは注意してください。</font>

[electron_opal](https://github.com/jannishuebl/electron_opal)というのがあるので、これで楽勝なんじゃないかと思ったらこれがなかなかちゃんと動いてくれません。
とりあえず、ElectronでOpalのコードを実行できたのでそこまでの道のりをその1として書こうと思います。


まずは`gem install`と思いきや、[RubyGems.org](https://rubygems.org/)に登録されていません。一応gemとして作られているので、`git clone`してきて*Gemfile*に

```ruby:Gemfile
gem 'electron_opal', path: '../electron_opal'
```

のように書いてローカルのソースコードを参照するようにしました。(たぶんソースをいじらないと動かなそうという予感がしたので…)
*README.md*はgithubが生成するデフォルトのままなので何の情報もありませんので、とりあえずソースを眺めます。

*[lib/electron_opal.rb](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb)*をみるとRaketaskになっているようなのでとりあえず、*Rakefile*を書きます。

```ruby:Rakefile
require 'bundler'
Bundler.require
```

taskとしては、`default`,`build`,`debug`があるので、とりあえず`build`を試みます。

```
rake aborted!
NoMethodError: undefined method `source' for nil:NilClass
...
```

当然のようにエラーを吐きます。
*[electron_opal/lib/electron_opal.rb:70](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb#L70)*でエラーのようなのでソースをみます。
`Sprockets::Environment#find_asset`で`nil`が返ってきているので、アセットがみつからないということが分ります。
とりあえず、Electronの流儀にそって、*main.rb*というファイルを作ります。

```main.rb
puts 'Hello world'
```

`rake build`します。同様のエラーです。
`asset_path`を追加する必要がありそうです。
[このへん](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb#L21-L22)パスをついかしているので、`config.path`に追加すればよさそうです。丁度良く`setup`メソッドが定義されています。
*Rakefile*に以下のように追加します。

```ruby:Rakefile
setup do |config|
  config.paths << 'app'
end
```

`main.rb`は`app`以下に移動しましょう。

ビルドはできました。

`rake`してみます。

electronコマンドがないと言われるので、`npm install -g electron`します。

再チャレンジ

<img width="532" alt="スクリーンショット 2016-12-15 1.01.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/15093/649a1382-1a30-fb0e-afa5-0017b6e88028.png">

Electron appがないと言われます。
Electron appとして成立させるためには、*package.json*が必要そうです。

```json:package.json
{
  "name": "electron_opal",
  "version": "0.0.1",
  "main": "build/main.js"
}
```

最低限、何が必要か分かりませんがこんな感じで。

```
App threw an error during load
ReferenceError: Opal is not defined
```

<p id='here'><font color='red'>&lt;!-- ここから下の記述に間違いがありました。<a href='http://qiita.com/youchan@github/items/9a2b0b9e5c511457773f'>15日目の記事</a>を参照してください。 --&gt;</font></p>

Opalが定義されていないと怒られるので、なんとかします。
ここからの戦いが長かったので、結論だけ

*[lib/electron_opal.rb:68](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb#L68)*

```ruby
load_asset_code = Opal::Processor.load_asset_code(env, asset_name) if options[:load_asset_code]
```
どうも`Opal::Processor`でロードしているのが良くなさそう。最新のOpal 0.10.3でも試したりしましたが`load_asset_code`は無くなっていました。
[Opalのドキュメント](http://opalrb.org/docs/guides/v0.10.3/static_applications.html)を確認すると、`Opal::Builder`を使うのが正しそうです。

*[lib/electron_opal.rb:48](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb#L48)*

```ruby
compile_js(config.app_class, load_asset_code: true)
```

を

```ruby
write_to("#{config.app_class}.js", Opal::Builder.build(config.app_path).to_s, Opal::Builder.build('opal'))
```

こんな風に`Opal::Builder`ように書きかえて、尚かつ、`opal`本体をコンパイルして含めるようにします。
`app_path`は*Rakefile*で指定します。

```ruby
  config.app_path = File.expand_path('../app/main.rb', __FILE__)
```

*[electron_opal.rb:86](https://github.com/jannishuebl/electron_opal/blob/master/lib/electron_opal.rb#L86-L87)*

```ruby
    f.write source
    f.write load_code
```

ここは順序が逆なので、入れかえます。

    $ bundle exec rake build
    $ bundle exec rake

で無事に`Hello world`と表示されました。

結構苦労したわりには、まだGUIアプリになっていません。そもそもelectron_opal`が中途半端すぎでした。
次回からはelectron_opalに変わるものを作りながらGUIアプリとして成立するようにしていきたいと思います。
そういうわけでしばらくシリーズものになりそうです。