LoginSignup
18
16

More than 5 years have passed since last update.

RailsアプリでBackbone.jsを使う(2015年版)

Posted at

Ruby on RailsとBackbone.js始めました。

Rails × Backbone.jsを試したくて調べて出てきた記事「RailsアプリでBackbone.jsを使う」を読み、まったく同じことをやろうとしたら色々ハマりました
自分がRailsもBackbone.jsも初心者なために陥ったのが大部分だと思いますが、4年近い歳月の間に変わってしまったことも多くあったようです。

そこで、目指すところは元記事と同じまま手順を2015年版に書き換えてみたいと思います。

Backbone.jsの本家ドキュメントにtodoリストをブラウザのLocalStorageを使って保存するチュートリアルがあります。
todo.js
今回は、このtodoアプリのバックエンドとして、Ruby on Railsを使うように変更してみたいと思います。

Rails

rails newrake db:migrateまで。

$ rails new todos
$ cd todos
$ echo "gem 'rails-backbone'" >> Gemfile
$ bundle install
$ rails g backbone:install
$ rails g scaffold todo title:string done:boolean
$ rake db:migrate

元記事ではbackbone.jsと依存ライブラリをダウンロードしてapp/assets/javascriptsに入れていましたが、今回はrails-backboneをgemとして追加することにします。

  • gemとして追加してやったほうが管理が楽

gem名はrails-backboneですがレポジトリ名はなぜかbackbone-railsです。ご注意ください。

  • 元記事と同じやり方だとAjax時にRailsのCSRF対策に引っかかってしまう

Backbone.syncをハックして避ける方法もあるようですが同gemでも回避できるようなので。

[backbone][rails][CSRF][ajax]backbone syncでcsrfタグもpostする方法
Backbone.jsでRailsのCSFR防止tokenをうまく扱う

View Template

元のチュートリアルのhtmlのbodyタグ内をapp/views/todos/index.html.erbにコピペします。

元記事のとおりhtmlをコピペしましょう。

scriptの読み込みはapplication.jsrequireで行うようになっているので以下の記述は削除します。

app/views/todos/index.html.erb
  <script src="spec/support/jquery.js"></script>
  <script src="spec/support/underscore.js"></script>
  <script src="spec/support/backbone.js"></script>
  <script src="backbone.localStorage.js"></script>
  <script src="todos.js"></script>

Separation

サンプルのTodoアプリではBackbone.jsで使うテンプレートをindex.html.erbに<script type="text/template">として読み込んでいます。このままだとerbの制御文字とunderscore.jsが競合してparse errorになるので元記事ではunderscore.jsのロジックを書き換えています。

同じやり方でも構いませんがサーバサイドとクライアントサイドで使用するファイルは極力分けて管理したいので今回はテンプレートを外部ファイル化してみます。

まず、index.html.erb内のテンプレート記述2つ(以下)を削除します。

app/views/todos/index.html.erb
<!-- Templates -->

<script type="text/template" id="item-template">
  <div class="view">
    <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
    <label><%- title %></label>
    <a class="destroy"></a>
  </div>
  <input class="edit" type="text" value="<%- title %>" />
</script>

<script type="text/template" id="stats-template">
  <% if (done) { %>
    <a id="clear-completed">Clear <%= done %> completed <%= done == 1 ? 'item' : 'items' %></a>
  <% } %>
  <div class="todo-count"><b><%= remaining %></b> <%= remaining == 1 ? 'item' : 'items' %> left</div>
</script>

次にapp/assets/javascripts/backbone/templateに以下の2ファイルを追加しましょう。

app/assets/javascripts/backbone/template/item-template.jst.ejs
<div class="view">
  <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
  <label><%- title %></label>
  <a class="destroy"></a>
</div>
<input class="edit" type="text" value="<%- title %>" />
app/assets/javascripts/backbone/template/stats-template.jst.ejs
<% if (done) { %>
  <a id="clear-completed">Clear <%= done %> completed <%= done == 1 ? 'item' : 'items' %></a>
<% } %>
<div class="todo-count"><b><%= remaining %></b> <%= remaining == 1 ? 'item' : 'items' %> left</div>

これらはjavascriptからそれぞれ以下のような形式で呼び出せます。

  • JST['backbone/templates/item-template']
  • JST['backbone/templates/stats-template']

テンプレートの分離はこれで完了です。

Backbone.js

app/assets/javascripts/backbone/todos.js.coffeeを削除し、本家のtodos.jsをコピーして配置します。

jstとして分離したテンプレートを使用するように変更します。

app/assets/javascripts/backbone/todos.js
  // The DOM element for a todo item...
  var TodoView = Backbone.View.extend({

    // Cache the template function for a single item.
    // template: _.template($('#item-template').html()),
    template: JST['backbone/templates/item-template']

(中略)

  // Our overall **AppView** is the top-level piece of UI.
  var AppView = Backbone.View.extend({

    // Our template for the line of statistics at the bottom of the app.
    // statsTemplate: _.template($('#stats-template').html()),
    statsTemplate: JST['backbone/templates/stats-template']

これだけで動くようになりますが、Rails使っているのに今更JavaScriptって無いんだろうな…と思いCoffeeScript化してみました。長くなるのでGistに貼り付けておきました。

Design

jsと同様にcssも本家からコピーしてきます。

cssを自前でscssにするのは…まァいいか、という気持ちです。変換をブラウザで行ってくれる便利サイト(css2sass)がありますので本家のtodos.cssをコピーしてここでscssに変換し、デフォルトで作成されているapp/assets/stylesheets/todos.css.scssに貼り付けましょう。

Todo削除アイコンdestroy.pngがそのままだと読み込めないので以下のように書き換えます。

app/assets/stylesheets/todos.css
#todo-list .destroy {
    position: absolute;
    right: 5px;
    top: 20px;
    display: none;
    cursor: pointer;
    width: 20px;
    height: 20px;
/*  background: url(destroy.png) no-repeat; */
    background: url(//localtodos.com/destroy.png) no-repeat;
}

Completion!

これにて完了です。rails sして動作確認しましょう。

Backbone.jsも引き続き学んでいくわけですが、このアプリを軸にMarionette.jsやらMongoDBやらも試していきたいと思っています。

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16