0

Having trouble rendering first page using rails and backbone. Please assume that I have all the gems properly installed and running. Most of the coffeescript files are generated using 'rails g backbone:scaffold Student', but I changed some files and directory structure. This is just to try to understand the process flow than anything else. I also loaded some student data in db. Finally, when this rails application is deployed (development) and I visit localhost:3000, I don't get the alert that is in initialize function.

Here are the files.


app/models/students.rb

class Student < ActiveRecord::Base
  attr_accessible :dob, :email, :name, :phone_number
end

app/controllers/students_controller.rb

class StudentsController < ApplicationController
  respond_to :html, :json

  def index
    respond_with (@students = Student.all)
  end
end

config/routes.rb

School::Application.routes.draw do

  resources :students

  root :to => 'students#index'

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>School</title>
  <%= stylesheet_link_tag    "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>
<body>
  <tbody>
    <div id="students">
      <%= yield %>
    </div>
  </tbody>
</body>
</html>

app/views/students/index.html.erb

<%= content_for :javascript do %>
  <%= javascript_tag do %>
    window.School.initialize({ students: <%= @students.to_json %> });
  <% end %>
<% end %>

app/assets/javascripts/application.js

//
//= require jquery
//= require jquery_ujs
//= require jquery-ui-1.8.18.custom.min
//
//= require underscore
//= require json2
//= require backbone
//= require backbone_rails_sync
//= require backbone_datalink
//= require backbone-forms
//= require school
//= require_tree ./models
//= require_tree ./collections
//= require_tree ./views
//= require_tree ./routers
//= require_tree ../templates
//= require_tree .

app/assets/javascripts/school.js.coffee

#= require_self
#= require_tree ../templates
#= require_tree ./models
#= require_tree ./collections
#= require_tree ./views
#= require_tree ./routers

window.School =
  Models: {}
  Collections: {}
  Routers: {}
  Views: {}
  initialize: (data) -> alert 'Hello for rails'

app/assets/javascripts/collections/students.js.coffee

class School.Collections.StudentsCollection extends Backbone.Collection
  model: School.Models.Student
  url: '/students'

app/assets/javascripts/models/student.js.coffee

class School.Models.Student extends Backbone.Model
  paramRoot: 'student'

app/assets/javascripts/routers/students_router.js.coffee

class School.Routers.StudentsRouter extends Backbone.Router
  initialize: (options) ->
    @students = new School.Collections.StudentsCollection()
    @students.reset options.students

  routes:
    "index"    : "index"
    ".*"       : "index"

  index: ->
    @view = new School.Views.Students.IndexView(students: @students)
    $("#students").html(@view.render().el)

app/assets/javascripts/views/students/index_view.js.coffee

School.Views.Students ||= {}

class School.Views.Students.IndexView extends Backbone.View
  template: JST["templates/students/index"]

  initialize: () ->
    @options.students.bind('reset', @addAll)

  addAll: () =>
    @options.students.each(@addOne)

  addOne: (student) =>
    view = new School.Views.Students.StudentView({model : student})
    @$("tbody").append(view.render().el)

  render: =>
    @$el.html(@template(students: @options.students.toJSON() ))
    @addAll()

    return this

app/assets/templates/students/index.jst.ejs

<h1>Listing students</h1>

<table id="students-table">
  <tr>
    <th>Name</th>
    <th>DOB</th>
    <th>Email</th>
  </tr>
</table>

html output

<!DOCTYPE html>
<html>
<head>
  <title>School</title>
  <link href="/assets/application.css?body=1" media="all" rel="stylesheet" type="text/css" />
<link href="/assets/students.css?body=1" media="all" rel="stylesheet" type="text/css" />
  <script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery-ui-1.8.18.custom.min.js?body=1" type="text/javascript"></script>
<script src="/assets/underscore.js?body=1" type="text/javascript"></script>
<script src="/assets/json2.js?body=1" type="text/javascript"></script>
<script src="/assets/backbone.js?body=1" type="text/javascript"></script>
<script src="/assets/backbone_rails_sync.js?body=1" type="text/javascript"></script>
<script src="/assets/backbone_datalink.js?body=1" type="text/javascript"></script>
<script src="/assets/backbone-forms.js?body=1" type="text/javascript"></script>
<script src="/assets/school.js?body=1" type="text/javascript"></script>
<script src="/assets/students/edit.js?body=1" type="text/javascript"></script>
<script src="/assets/students/index.js?body=1" type="text/javascript"></script>
<script src="/assets/students/new.js?body=1" type="text/javascript"></script>
<script src="/assets/students/show.js?body=1" type="text/javascript"></script>
<script src="/assets/students/student.js?body=1" type="text/javascript"></script>
<script src="/assets/models/student.js?body=1" type="text/javascript"></script>
<script src="/assets/collections/students.js?body=1" type="text/javascript"></script>
<script src="/assets/views/students/edit_view.js?body=1" type="text/javascript"></script>
<script src="/assets/views/students/index_view.js?body=1" type="text/javascript"></script>
<script src="/assets/views/students/new_view.js?body=1" type="text/javascript"></script>
<script src="/assets/views/students/show_view.js?body=1" type="text/javascript"></script>
<script src="/assets/views/students/student_view.js?body=1" type="text/javascript"></script>
<script src="/assets/routers/students_router.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>
  <meta content="authenticity_token" name="csrf-param" />
<meta content="46vcYK8H3HIUfZh9wfu+AtzCKs+/2TnESA2ILxhFx0E=" name="csrf-token" />
</head>
<body>
  <tbody>
  <div id="students">

  </div>
  </tbody>
</body>
</html>

1
  • Changing app/views/students/index.html.erb to below code solves the problem <script type="text/javascript"> $(function() { window.Sepms.initialize({ students: <%= @students.to_json.html_safe -%> }); }); </script> Commented Mar 8, 2013 at 10:56

1 Answer 1

1

You have a couple of problems that are seemingly related and unrelated at the same time.

  1. The reason your index doesn't render correctly is because you have a content block for a a named yield that doesn't exist. To get <%= content_for :javascript do %> to work, add the following to application.html.erb:

    <%= yield :javascript %>

    However, this will get your code to display, it most likely will not get it to run correctly.

  2. Since you are using the rails-backbone gem and leveraging the use of templates, you simply need to have the following in your index.html.erb:

     <div id="students"></div>
    

And then instantiate your backbone router in your index.html.erb by using:

<script type="text/javascript">
  $(function(){
   try {
     window.SchoolRouter = new School.Routers.StudentsRouter({ students: <%= @students.to_json %> });
     backbone.history.start();
   }catch(e){
     alert(e); // alert so that you see it.
   }
  });
</script>

When it comes to JavaScript, make sure you're using FireBug or the Dev panels in your browser. console.log() is your best friend.

Sign up to request clarification or add additional context in comments.

3 Comments

Is it absolutely necessary to use script tags? I realize this is a bit of a chicken egg... but isn't there a way to have the app initialized in the rails asset pipeline way? #nomorescripttags
Not that I'm aware of. If there was, it almost seems like an unnecessary abstraction for a rather simple issue. If you're using coffeescript though in your rails, you could use the $ -> to signify the same thing as onDocumentReady().
I think we can add //= require backbone/init to our application.js file, and then put all this initialization code in app/assets/javascript/backbone/init.js. That's the pattern I've adopted in my projects. I think I will add a detailed description of my setup as an alternative answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.