UnderOSを使ってみる

RubyMotion歴約一年でそのうち半年くらい[ProMotion](https://github.com/clearsightstudio/ProMotion "ProMotion")を使ってアプリを作っているのですが未だ完成しません(*開発中の[RapidNews](https://github.com/ofl/RapidNews)*)。

ProMotionについて書こうと思ったのですがネタが思い浮かばなかったので最近本元のTwitterでささやかれたフレームワーク「[UnderOS](https://github.com/under-os/under-os)」を紹介します。


##実際の例

まずはこうした計算機の画面。


![th_under_os2.jpg](https://qiita-image-store.s3.amazonaws.com/0/10362/54f48573-399c-f001-228a-16a719880e1e.jpeg "th_under_os2.jpg")


この画面をUnderOSで構成するのに必要なのは


```HTML:calculator.html
<!-- app/layouts/calculator.html -->

<page title="Calculator">
  <label id="result">0</label>

  <button class="row5 col1 top">C</button>
  <button class="row5 col2 top">±</button>
  <button class="row5 col3 top">%</button>

  <button class="row5 col4 ops">÷</button>
  <button class="row4 col4 ops">×</button>
  <button class="row3 col4 ops">-</button>
  <button class="row2 col4 ops">+</button>
  <button class="row1 col4 ops">=</button>

  <button class="row4 col3">9</button>
  <button class="row4 col2">8</button>
  <button class="row4 col1">7</button>
  <button class="row3 col3">6</button>
  <button class="row3 col2">5</button>
  <button class="row3 col1">4</button>
  <button class="row2 col3">3</button>
  <button class="row2 col2">2</button>
  <button class="row2 col1">1</button>
  <button class="row1 col1 double">0</button>

  <button class="row1 col3">.</button>
</page>
```


ファイル拡張子もずばり.htmlなこれと


```CSS:calculator.css
/* app/styles/calculatro.css */

page {
  background-color: darkgray;
}

label {
  left:        0;
  top:         80;
  color:       white;
  height:      80;
  width:       320;
  font-size:   80;
  text-align:  right;
}

button {
  width:         79px;
  height:        79px;
  color:         black;
  background:    white;
  border-radius: 0px;
  font-size:     40;
}

button.double { width: 159; }
button.ops    { background: yellow; font-size: 20; }
button.top    { background: lightgray; font-size: 20; }

.row1 { bottom: 0px;   }
.row2 { bottom: 80px;  }
.row3 { bottom: 160px; }
.row4 { bottom: 240px; }
.row5 { bottom: 320px; }

.col1 { left: 0;   }
.col2 { left: 80;  }
.col3 { left: 160; }
.col4 { left: 240; }
```


これまたストレートに.cssファイル。セミコロンまで使っていて芸が細かいですね。後発だけに継承の書き方も洗練されてます。そして


```Ruby:calculator_page.rb
#app/pages/calucurator_page.rb

class CalculatorPage < UnderOs::Page

  def initialize
    @label = first('#result')

    find('button').each do |b|
      b.on(:tap){|e| handle_tap(e)}
    end
  end

  def handle_tap(event)
    case event.target.text
    when '0','1','2','3','4','5','6','7','8','9','.'
      @label.text  = '' if ['0', @first_value].include?(@label.text)
      @label.text += event.target.text if @label.text.size < 18
    #略
  end

  def calculate
    return if ! @first_value

    values = [@first_value, @label.text]
    values = values.any?{|v| v.include?('.')} ? values.map(&:to_f) : values.map(&:to_i)

    @label.text = values[0].send(@operator, values[1]).to_s
  end

end
```


Rubyです。Objective-Cっぽさは微塵も感じられません、。さらに`find(‘button’)`でボタンを一括して指定できたり`b.on(:tap)`でイベントを拾うなどJQuery的な書き方が意識されていてRuy未経験者でも十分親しみやすいと思います。


##使い方

前後しますが使い方はまず


```
gem install under-os
```


テンプレートが用意されているので


```
mkdir -p ~/Library/RubyMotion/template/uos
git clone https://github.com/under-os/under-os-template.git ~/Library/RubyMotion/template/uos
```


そうするとappフォルダには


```
`-- app
    |-- layouts
    |   `-- home.html
    |-- models
    |-- pages
    |   `-- home_page.rb
    |-- styles
    |   `-- application.css
    |-- views
    `-- config.rb
```


これらのファイルが作成されます。
layoutsにHTML、pagesにRubyファイル、stylesにCSSを配置、その他にmodelsやviewsというフォルダが用意されています。

config.rbが見慣れませんが中身は


```Ruby:config.rb
UnderOs::App.start do
  config.navbar    = true
  config.root_page = HomePage.new
end
```


のような感じでapp_delegateを隠匿しています。

##さらに
UnderOSが狙いとしているところはおよそ理解できたとして、ではページを構成するのに常にHTML,CSS,Rubyの３点セットが必要なのかというとそうではなく、


```Ruby:stuff_page.rb
#app/pages/stuff_page.rb

class StuffPage < UnderOs::Page
  def initialize
    self.title = "Various Stuff"

    @box = View.new(style: {
      top:          50,
      left:         50,
      width:        100,
      height:       100,
      background:   :red,
      borderRadius: 10,
      borderWidth:  2,
      borderColor:  :green
    })
    @b2 = View.new(style: {background: :blue})
    insert @box.insert(@b2)

    insert Icon.new(:cog).position(x: 50, y: 300)
  end
end
```


といようにコードだけで完結させることもできます。


```Ruby
  insert Icon.new(:cog).position(x: 50, y: 300)
```


でviewを追加、入れ子にする場合は


```Ruby
  insert @box.insert(@b2)
```


と書きます。もちろんコードだけでなくInterface Builderで作ったviewを読み込むこともできるようです。

##試してみての感想
ネイティブアプリのコードをHTMLやCSS風に書くことを目指したフレームワークはRubyMotionに限らずこれまでにもいろいろ作られてきたかと思いますが、その中でも結構、感動的な再現度ではないでしょうか。

一方で華麗なマジックがほど裏側ではえげつないことしているのでは？と疑いを持つことかと思いますが、作者はUnderOSは’thin web-like wrapper’だと主張しています。
実際に今の段階では小一時間もあればコード全体を目を通すことができますし、メタプログラミングなどが駆使されて読みづらいというようなこともありませんでした。

とはいっても既に書き慣れているユーザーだとあえて手を出す必要性は感じにくいかもしれません。ただ使う使わないは別にしてもRubyMotionの裾野を広げる可能性のある注目すべきプロジェクトかと思います。

公式サイト
http://under-os.com