Opal、Vue.js、Sinatra
気になっていたOpalを試してみるのに、どうせならとVue.jsを組み合わせよう! と気軽に始めてみたら、思いのほかのめり込んでしまったという話。(はまった、とも)
OpalはRubyで書いたコードをJavaScriptで実行するためのフレームワーク。すごそうだなとは思っていたのだけど、実際にそれなりのコードを書いてみたところ、すごかった。
他のJavaScriptフレームワーク(今回ならVue.js)と組み合わせるとなると気をつかうところが出てくるものの、単体で考えるとこれもうRubyなんじゃってくらいRubyらしく書けてしまう。がんばってるなあ。
で、実際に書いてみたコードなんだけど、こんなの感じのが動きます。
class Calc < Vue
OP = { add: :+, sub: :-, mul: :*, div: :/, mod: :% }
data waiting: -> { [] }
data calculator: -> { OP.keys.to_n }
def new_card
waiting << { num1: nil, num2: nil, dragging: false }.to_n
end
end
class CalcCard < VueComponent
include DragAndDropHelper
data :num1, :num2, dragging: false
template '#card-template'
def drag_start(ev)
self.dragging = true
set_dnd_data(ev, to_data);
end
def drag_end(ev)
self.dragging = false
end
end
class CalcPlace < VueComponent
include DragAndDropHelper
props :op
data :num1, :num2
template '#place-template'
def drag_over(ev)
set_drop_effect(ev, :copy)
end
def drop(ev)
data = get_dnd_data(ev)
apply_data(data)
end
computed
def op_sym
Calc::OP[op].to_n
end
def result
sym = op_sym
return unless sym
return unless num1.is_a?(Numeric) && num2.is_a?(Numeric)
num1.public_send(sym, num2)
end
end
Document.ready? do
CalcCard.activate!
CalcPlace.activate!
Calc.new('#calc') unless Element.find('#calc').empty?
end
(opal-vue-trialから一部抜粋)
Rubyに慣れている人なら、Rubyの知識はわりとそのまま使えちゃう。問題はRubyとJavaScriptの間の値の相互変換。
いや、Opalの実行環境はJavaScriptだから、どちらもJavaScriptなのだけど、OpalではRubyのためのクラス(というかオブジェクト)を用意しているので、それらの間で変換しなくてはらならない場合が出てくる。特に他のフレームワークといっしょに使うとき。
結局のところ、どういうときにどちらの値で持てばよいかの見極めなのだろうと思う。これは実際に動くものを書いてみるとだんだん分かってくるのだが、そのためには試行錯誤が必要となる。まあ、それもなかなか楽しい。久しぶりにがっつり時間をつっこんだ。
なお、フレームワークではなくてライブラリならそれほど苦労せずに使えと思う。また、jQueryなど有名なライブラリについてはバインディングがある。