TL;DR
全部Rubyでかけるのがうま味? Rubyに慣れ親しんだJS初心者は嬉しいかも? なOpal入門してみます。導入からアプリがちょっと動くところまで。
Opal導入する
適当なプロジェクトを作成して、準備します。
GemfileにOpalを追加
gem 'opal-rails'
app/assets/javascripts/application.js を app/assets/javascripts/application.js.rbに変更して中身も変える
require 'opal' require 'opal_ujs' require 'turbolinks' require_tree '.'
したら、コントローラを作ってみます。
$ rails g controller Sample index
結果
create app/controllers/sample_controller.rb route get 'sample/index' invoke erb create app/views/sample create app/views/sample/index.html.erb invoke test_unit create test/controllers/sample_controller_test.rb invoke helper create app/helpers/sample_helper.rb invoke test_unit invoke assets invoke opal create app/assets/javascripts/sample.js.rb invoke scss create app/assets/stylesheets/sample.scss
Opalがこんなものを作ってくれましたね。
create app/assets/javascripts/sample.js.rb
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use Opal in this file: http://opalrb.org/
#
#
# Here's an example view class for your controller:
#
class SampleView
# We should have <body class="controller-<%= controller_name %>"> in layouts
def initialize(selector = 'body.controller-sample')
@selector = selector
end
def setup
on(:click, 'a', &method(:link_clicked))
end
def link_clicked(event)
event.prevent
puts "Hello! (You just clicked on a link: #{event.current_target.text})"
end
private
attr_reader :selector, :element
# Uncomment the following method to look for elements in the scope of the
# base selector:
#
# def find(selector)
# Element.find("#{@selector} #{selector}")
# end
# Register events on document to save memory and be friends to Turbolinks
def on(event, selector = nil, &block)
Element[`document`].on(event, selector, &block)
end
end
SampleView.new.setup
おお、なんとなく読めます。動作確認してみましょう。
自動生成のコードでは、尻のsetupメソッドでaタグにlink_clickedを呼ぶクリックイベントを定義してくれていそうなので、aタグ設置したりしてみようと思います。クラス宣言の外に下記を追加して、/sample/indexに行きましょう。
Document.ready? do
Element.find('body').html = '<h1>Hello World from Opal!</h1> <a href="#">Hello</a>'
end
htmlがHelloみたいな雰囲気になり、ひとつリンクが設置されているはずです。リンクをクリックするとlink_clickedが呼ばれてコンソールにputsしてくれますね。ほへー。
自動生成されたコードを参考にしつつ、さっき追記したものを消してもうちょっと触ってみる。
/app/views/sample/index.html.erb
<h2>sample</h2> <input type="text" id="sample_input" data-target="#sample_text"> <input type="button" id="change_color" data-target="#sample_text" value="色変えるボタン"> <div id="sample_text"></div>
/app/assets/javascripts/sample.js.rb
略
def setup
on(:click, 'a', &method(:link_clicked))
on(:input, '#sample_input', &method(:value_changed))
on(:click, '#change_color', &method(:change_color))
end
def link_clicked(event)
event.prevent
puts "Hello! (You just clicked on a link: #{event.current_target.text})"
end
def value_changed(event)
Element.find(event.target.data['target']).text = event.target.value
end
def change_color(event)
Element.find(event.target.data['target']).css("color", "red")
end
略
こんなんになる。

jQueryより見た目はスッキリするし、諸々をRubyで統一できるのはもしかしたらハッピーかもしれないですね。今回はシンプルにサクッとなのでerbだったけど他のテンプレートエンジンに乗せかえるのもそんな問題なさそうです。