Help us understand the problem. What is going on with this article?

Mithril.jsをRailsで始める

More than 3 years have passed since last update.

Mithril は名前を聞いたことがある程度で、特に触ってみる予定はなかったのですが、Shibu's Diary: 世界最速でMithril本をリリースした話 を見て俄然興味が湧いたので、早速、黒ムツ本 を購入して読みました。
コンパクトで大変読みやすかったです。オススメ。コードもMITライセンスで公開 されていて嬉しい。

あえてRailsで

本を読んでなんとなく理解できたところで、次は実際に触ってみるフェーズ。
今後いろいろといじっていくにあたり、サーバサイドは使い慣れているRailsでやりたい。
ということで、まずはTodoのサンプルをRails化してみました。

全コードはこちらにあります。
https://github.com/tnantoka/my-mithril

やったこと

Mithrilを入れる

mrsweaters/mithril-rails は古かっ1し、今回はMSX を使う予定もなかったので、rails-assets で入れました。

Gemfile
source 'https://rails-assets.org' do
  gem 'rails-assets-mithril'
end
$ bundle
app/assets/javascripts/application.js
//= require mithril

コンポーネントを書く

app/assets/javascripts/components/todo.coffeeに置きました。

モデル

class Todo
  constructor: (data = {}) ->
    @description = m.prop(data.description || '')
    @done = m.prop(false)

  @list: ->
    m.request(method: 'GET', url: '/todos', type: Todo, initialValue: [])
  @save: (list) -> 
    data =
      todos: list.filter (t) -> !t.done()
    MyMithril.request(method: 'POST', url: '/todos', data: data)

MyMithril.requestcsrf-tokenを追加してm.requestを呼ぶ自作関数です。https://github.com/tnantoka/my-mithril/blob/master/app/assets/javascripts/my-mithril.coffee

mithril-rails使えば勝手にやってくれる?(未確認)

ビューモデル

Enterキーで保存できるようにしています。

vm =
  init: ->
    vm.list = Todo.list()
    vm.description = m.prop('')
    vm.entered = m.prop(false)
  add: ->
    if vm.description().length
      todo = new Todo(description: vm.description())
      vm.list().push(todo)
      vm.description('')
      Todo.save(vm.list())
  toggle: (value) ->
    @done(value)
    Todo.save(vm.list())
  onkeyup: (value) ->
    vm.description(value) unless vm.entered()
    vm.entered(false)
  onkeypress: (e) ->
    if e.keyCode == 13
      vm.entered(true)
      vm.add()
    else
      m.redraw.strategy('none')

コントローラー

controller = ->
  vm.init()

ビュー

onchangeはfocusがある間は発生しない(忘れててちょっとハマった)ので、onkeyupで入力中のキーワードをvm.descriptionに設定しています。

view = ->
  m 'div', [
    m '.row', [
      m '.col-sm-4', [
        m '.input-group', [
          m 'input.form-control', {
            value: vm.description()
            onkeyup: m.withAttr('value', vm.onkeyup)
            onkeypress: vm.onkeypress
          }
          m 'span.input-group-btn', m 'button.btn.btn-primary', onclick: vm.add, 'Add'
        ]
      ]
    ]
    m 'div', vm.list().map (t) ->
      textDecoraton = if t.done() then 'line-through' else 'none'
      m '.checkbox', [
        m 'label', [  
          m 'input[type=checkbox]', onclick: m.withAttr('checked', vm.toggle.bind(t)), value: t.done()
          m 'span', { style: { textDecoration: textDecoraton } }, t.description()
        ]
      ]
  ]

コンポーネントを呼び出す

手抜きでViewから呼んでます。

app/views/welcome/todo.html.slim
javascript:
  m.mount($('#app').get(0), components.todo.component);

サーバーサイドを実装する

createでは受け取ったデータをsessionに突っ込んで、indexではそれをそのまま返しています。

app/controllers/todos_controller.rb
class TodosController < ApplicationController
  def index
    render json: session[:todos].to_a
  end

  def create
    session[:todos] = params[:todos]
    render nothing: true
  end
end

テストを書く

それなりに長いので割愛。
https://github.com/tnantoka/my-mithril/blob/master/spec/javascripts/todo_spec.coffee にあります。

実行には、Teaspoon を使いました。README通りやればCoverageもちゃんと取れてよかったです。
Sinon.JSのserver.respondImmediately = trueがなぜか効かなかった(?)り、npm module使えるの?とかまだわかってないところだらけですが。

動いた!

http://my-mithril.bornneet.com/ で動いています。

tweet-boxの方はReact.js Introduction For People Who Know Just Enough jQuery To Get By · React for Designers の劣化コピーです。(Rails関係ない)

感想

まだ触り始めたばかりですが、vue.js ぐらい手軽に利用できて、しかもrouter2 も付いてきて、設計指針も示してくれる(これは本が親切なのもありますが)ので、片手間フロントエンダーには大変ありがたいと思いました。

だいぶ慣れてきたので、次は何か大きめのものを作ってみる予定。


  1. 僕がMithrilの勉強を始めた先週末時点では数ヶ月放置されてた。今はちゃんと最新版にアップデートされてるみたい。 

  2. ラウターと読む癖を付けよう! 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away