LoginSignup
30
32

More than 5 years have passed since last update.

backbone-on-railsでモデル一覧を表示する。

Last updated at Posted at 2013-04-18

既存のRailsプロジェクトにbackbone.jsを使ってみようと思い立って、backbone-on-railsを入れてみたのでメモ。

Gemfileに以下を追加する。

Gemfile
gem 'backbone-on-rails'

以下を実行する。

bash
bundle install
rails generate backbone:install

そうすると、assets以下に以下のディレクトリができる。

  • javascript/collections
  • javascript/models
  • javascript/routers
  • javascript/views
  • templates

templatesは、html置き場。
ecoというテンプレートエンジンを使って書ける。ecoはCoffeeScriptで記述するテンプレートだけれど、記述がほぼerbのように書けるので、erbで書いてきた人達にはストレスはないと思う。slimで書いている自分にはややストレス…。

試しにscaffoldでやってるベタなmodelに対してやってみる。
backboneのscaffoldを作成する。

bash
rails generate backbone:scaffoild hoges

最初はアラートが出るようになっているので、まずコメントアウトしておく。
rails_project.js.coffeeは各々のプロジェクト名になっているので注意。

rails_project.js.coffee
window.RailsProject =
  Models: {}
  Collections: {}
  Views: {}
  Routers: {}
  initialize: ->
    # alert 'Hello from Backbone!'

$(document).ready ->
  RailsProject.initialize()

Hello World的なのは、他の記事を参考にしてください。よくあるから。

この記事では、次の順序でhogeリストを出すところまでやる。

  1. collectionを定義する。
  2. routerを定義する。
  3. collectionを処理するviewを定義する。
  4. 個別のmodelを処理するviewを定義する。
  5. routerを起動してデータを取ってくる。

1つ目はcollectionを定義。

assets/javascript/collections/hoges.js.coffee
class RailsProject.Collections.Hoges extends Backbone.Collection

  model: RailsProject.Models.Hoge
  url: 'hoges'

URLは、HogesクラスがHogeモデルのJSONを取りにいくパス。
fetchメソッドを呼ぶと、/hogesにAjaxでアクセスしてJSONを取ってくることを想定している。

2つ目に、routerを定義。

assets/javascript/routers/hoges_router.js.coffee
class RailsProject.Router.Hoges extends Backbone.Router
  routes:
    '': 'index'

  initialize: ->
    @collection = new RailsProject.Collections.Hoges()
    @collection.fetch(reset: true)

  index: ->
    view = new RailsProject.Views.HogesIndex(collection: @collection)
    $('#main').html(view.render().el)

routerからviewに複数のHogeを渡しています。
@collection.fetch(reset: true) が肝です。後で解説します。

3つ目に、collectionを処理するviewの定義。

assets/javascript/views/hoges/hoges_index.js.coffee
class RailsProject.Views.HogesIndex extends Backbone.View

  template: JST['hoges/index']

  initialize: ->
    @collection.on('reset', @render, this)

  render: ->
    $(@el).html(@template())
    @collection.each(@appendHoges)
    this

  appendHoges: (hoge) ->
    view = new RailsProject.Views.Hoge(model: hoge)
    $('#hoges').append(view.render().el)

routerのところで言っていた、肝の部分ですが、initializeで@collectionのリセットが走ったらrenderメソッドを実行するように書いています。これは、Ajaxで@collectionを取ってくる前に、一度renderメソッドが実行されるため、@collectionが取得できたら再度renderを実行させるためです。
routerの@collection.fetchメソッドで、reset: trueに設定していたのは、フェッチし終わったらリセットしたと認識させるためです。私が参考にしていたサンプルだとこの部分が省略されていたので、すごくハマりました。バージョンが変わってfetchしたときのデフォルトの動作が変わったのかもしれません。

appendHogesメソッドで、4つ目で定義するクラスをインスタンス化して、ul#hogesに詰め込んでいます。そのul#hogeは、template: JST['hoges/index']で読み込んでいます。

では、templateを定義します。

assets/templates/hoges/index.jst.eco
<ul id="hoges"></ul>

このul#hogesの中にリストを表示するのがゴールとします。

4つ目に、個々のmodelを処理するviewを書きます。

assets/javascript/views/hoge.js.coffee
class RailsProject.Views.Hoge extends Backbone.View
  template: JST['hoges/age']
  tagName: 'li'

  render: ->
    $(@el).html(@template(hoge: @model))
    this

このviewで読み込むtemplateを定義します。

assets/templates/hoges/hoge.jst.eco
<%= @hoge.get('name') %>

backbone.jsで、モデルの要素を取りいく場合は、model.get('attribute_name')になります。model.attribute_nameというふうにはいかないので、注意が必要です。

5つ目に、このルーターを起動させます。

assets/javascript/hoges.js.coffee
$ ->
  # hogesコントローラーのときだけ実行するように書いたとして…
  if $('#hoges_controller').is('*')
    window.router = new RailsProject.Routers.Hoges()
    Backbone.history.start()

これで、railsプロジェクトのhogesコントローラーにアクセスするとリストが表示される…はず…。

30
32
1

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
30
32