SlideShare una empresa de Scribd logo
1 de 89
SINGLE PAGE APPS
      WITH
BACKBONE.JS & RAILS
      Prateek Dayal
     SupportBee.com
HOW I LEARNED TO STOP
      WORRYING
 AND LOVE JAVSCRIPT!
BUT I LOVE JQUERY!
VANILLA JQUERY IS GREAT
 FOR A SIMPLE WEBSITE
BUT YOU WANT TO BUILD A
SINGLE PAGE APPLICATION
Unless you’re a really fastidious coder, some sort of
library to help structure large-scale JavaScript
applications is important -- it’s far too easy to
degenerate into nested piles of jQuery callbacks, all
tied to concrete DOM elements.

                                      Jeremy Ashkenas
;)
COMPLEX SINGLE PAGE APPS
         HAVE
• All   of the client logic in Javascript
• All   of the client logic in Javascript

• Updates     to many parts of the UI on changes to
 data
• All   of the client logic in Javascript

• Updates     to many parts of the UI on changes to
 data

• Templating     on the client side
TO NOT GO CRAZY
BUILDING IT, YOU NEED
•A   MVC like pattern to keep the code clean
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements

•A   better way to manage events and callbacks
•A   MVC like pattern to keep the code clean

•Atemplating language like HAML/ERB to easily
render view elements

•A   better way to manage events and callbacks

•A   way to preserver browser’s back button
•A   MVC like pattern to keep the code clean

•A templating language like HAML/ERB to easily
 render view elements

•A   better way to manage events and callbacks

•A   way to preserver browser’s back button

• Easy Testing   :)
FORTUNATELY, THERE IS HELP!
SproutCore
Cappuccino
BUT THEY ARE BIG
AND HAVE A
LEARNING CURVE
• 3.9   kb packed and gzipped
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js

• You    need jQuery or Zepto for Ajax
• 3.9   kb packed and gzipped

• Only   dependency is underscore.js

• You    need jQuery or Zepto for Ajax

• Annotated    source code
MVC
MODELS, VIEWS &
 COLLECTIONS
MODELS
MODELS


• Data   is represented as Models
MODELS


• Data   is represented as Models

• Can   be Created, Validated, Destroyed & Persisted on Server
MODELS


• Data   is represented as Models

• Can   be Created, Validated, Destroyed & Persisted on Server

• Attribute   changes trigger a ‘change’ event
SB.Models.TicketSummary = Backbone.Model.extend({
  id: null,
  subject: null,
  name: 'ticket',
});
COLLECTIONS
COLLECTIONS

•A   collection of models
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh

• Can   fetch models from a given url
COLLECTIONS

•A   collection of models

• Triggers   events like add/remove/refresh

• Can   fetch models from a given url

• Can keep the models sorted if you define a comparator
 function
SB.Collections.TicketList = Backbone.Collection.extend({
  model: SB.Models.TicketSummary,

  url: "/tickets",
  name: "tickets",

   initialize: function(models, options){
     // Init stuff if you want
   }
});
VIEWS
VIEWS



• They   are more like Rails’ Controllers
VIEWS



• They   are more like Rails’ Controllers

• Responsiblefor instantiating Collections and binding events
 that update the UI
SB.Views.TicketListView = Backbone.View.extend({

  tagName: 'ul',

  initialize: function(){

    this.ticketList = new SB.Collections.TicketList;

    _.bindAll(this, 'addOne', 'addAll');


    this.ticketList.bind('add', this.addOne);

    this.ticketList.bind('refresh', this.addAll);

    this.ticketList.bind('all', this.render);


    this.ticketList.fetch();

  },

  addAll: function(){

    this.ticketList.each(this.addOne);
  },

   addOne: function(ticket){

    var view = new SB.Views.TicketSummaryView({model:ticket});

    $(this.el).append(view.render().el);
   }
});
SB.Views.TicketSummary = Backbone.View.extend({

 
     
 
 
 
 
 
 
 
 
  initialize: function(){

 _.bind(this, 'render');

 if(this.model !== undefined){

      this.model.view = this;

 }
  },

 events: {

 'click': 'openTicket'
 },

 openTicket: function(){

 window.location = "#ticket/" + this.model.id;
 },

  render: function(){

 $(this.el).html(SB.Views.Templates['tickets/summary']
(this.model.toJSON()));

 return this;
  }

 
    
 
 
 
 
 
 
 
 
});
HANDLEBARS!
{{#ticket}}
  <div class="listing-cell name">
   <p>{{nameOrEmail requester}} ({{replies_count}})</p>
  </div>

  <div class="listing-cell subject">
    
 <a href="#{{id}}">
    
 {{#unread}}
    
 <b>{{subject}}</b>
    
 {{/unread}}
    
 {{^unread}}
    
 {{subject}}
    
 {{/unread}}
    
 </a>
  </div>
{{/ticket}}
URLS
URLS



• Collections   can have a url
URLS



• Collections   can have a url

• Models   can have a url or they can derive it from collection’s
 url
◦   create → POST   /collection
◦   read → GET   /collection[/id]
◦   update → PUT   /collection/id
◦   delete → DELETE   /collection/id
FINALLY, CONTROLLERS
• Used   for setting up the routes
• Used   for setting up the routes

• You   can add new routes during runtime
SB.Controllers.AgentHome = Backbone.Controller.extend({
 routes: {

 "": "dashboard", // http://app_url

 ":id": "openTicket" // http://app_url#id
 },

    dashboard: function(){

      var view = new SB.Views.TicketListView;

      $("#ticket").hide();

      $("#list").html(view.el);

      $("#list").show();
    },

  openTicket: function(id){

 var view = new SB.Views.TicketView({model : new
SB.Models.Ticket({id : id})});

 $("#list").hide();

 $("#ticket").html(view.el);

 $("#ticket").show();
  }
});
window.controller = new SB.Controllers.AgentHome
• Initiates   a new controller instance
• Initiates   a new controller instance

• which   matches the dashboard route
• Initiates   a new controller instance

• which   matches the dashboard route

• and   creates a instance of TicketListView
• Initiates   a new controller instance

• which   matches the dashboard route

• and   creates a instance of TicketListView

• and   a TicketList collection is created
• TicketList
           collection fetches tickets and triggers the
 refresh event
• TicketList
           collection fetches tickets and triggers the
 refresh event

• Refresh handler renders a TicketSummary view for
 each ticket and adds it to the top level element
• Every Ticket   Summary row has an onclick handler
• Every Ticket   Summary row has an onclick handler

• which   changes to url to #ticket_id
• Every Ticket   Summary row has an onclick handler

• which   changes to url to #ticket_id

• which   matches the openTicket route
SERVER SIDE
ActiveRecord::Base.include_root_in_json = false
• Youcan use as_json to customize the json
 responses
• Youcan use as_json to customize the json
 responses

• Or   you can use Restfulie
• Youcan use as_json to customize the json
 responses

• Or   you can use Restfulie

• Restfulie   lets you easily put links in representations
 too
collection(@items, :root => "items") do |items|
    items.link "self", items_url

      items.members do |m, item|
          m.link :self, item_url(item)
          m.values { |values|
              values.name   item.name
          }
      end
end
NOT JUST FOR API BACKED
        MODELS
//window.AgentHomeController = new SB.Controllers.AgentHome;
window.mainView = new SB.Views.Main;
mainView.screens.add(new SB.Models.Screen({
  title: 'Dashboard',
  href: '#dashboard',
  listings: [

 {

 
       title: 'New Tickets',

 
       url: '/tickets?label=unanswered&replies=false'

 },

 {

 
       title: 'Ongoing Tickets',

 
       url: '/tickets?label=unanswered&replies=true'

 },

 {

 
       title: 'Starred Tickets',

 
       url: '/tickets?starred=true'

 }
   ]
}));
TESTING
JASMINE FTW!
beforeEach(function(){
   var ticket = new SB.Models.TicketSummary({id: 1,

 
     
 
 
 
 
 
 
 
 
 subject: "A Ticket",

 
     
 
 
 
 
 
 
 
 
 replies_count: 0,

 
     
 
 
 
 
 
 
 
 
 requester: {id : 1,

 
     
 
 
 
 
 
 
 
 
 email: 'requester@example.com',

 
     
 
 
 
 
 
 
 
 
 name: 'Requester',

 
     
 
 
 
 
 
 
 
 
 thumbnail: 'thumbnail-url'}

 
     
 
 
 
 
 
 
 
 
 });
   this.view = new SB.Views.TicketSummary({model: ticket});
   this.view.render();
});

it("should render a ticket summary correctly", function(){
   expect($(this.view.el)).toHaveText(/A Ticket/);
   expect($(this.view.el)).toHaveText(/Requester/);
});

it("should change the url on click", function(){
   var currentLoc = window.location.toString();
   $(this.view.el).click();
   expect(window.location.toString()).toBe(currentLoc + "ticket#1");
});
SINON FOR MOCKS/STUBS
beforeEach(function(){
  this.server = sinon.fakeServer.create();
  this.server.respondWith("GET", "/tickets_url_mock_server",

 
     
 
 
 
       [200, { "Content-Type": "application/json" },

 
     
 
 
 
 
 '{"tickets":[{"id": 1, "subject": "Ticket 1"},{"id": 2, "subject":
"Ticket 2"}]}'

 
     
 
 
 
 ]);
});

it("should instantiate view when tickets are fetched", function(){

  var viewMock = sinon.mock(SB.Views);

  viewMock.expects("TicketSummary").once().returns(new Backbone.View);
  viewMock.expects("TicketSummary").once().returns(new Backbone.View);

  var view = new SB.Views.TicketList({url: "/tickets_url_mock_server"});

   this.server.respond();
   viewMock.verify();
   expect($(view.render().el).children().length).toBe(2);
});
QUESTIONS?

prateek@supportbee.com
     @prateekdayal

  http://supportbee.com

Más contenido relacionado

La actualidad más candente

Templates
TemplatesTemplates
Templatessoon
 
Angular JS blog tutorial
Angular JS blog tutorialAngular JS blog tutorial
Angular JS blog tutorialClaude Tech
 
Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesjerryorr
 
Presentation.Key
Presentation.KeyPresentation.Key
Presentation.Keyguesta2b31d
 
SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery EssentialsMark Rackley
 
Why I Love JSX!
Why I Love JSX!Why I Love JSX!
Why I Love JSX!Jay Phelps
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
How routing works in angular js
How routing works in angular jsHow routing works in angular js
How routing works in angular jscodeandyou forums
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
 
Resource and view
Resource and viewResource and view
Resource and viewPapp Laszlo
 
Rails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiRails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiPivorak MeetUp
 
jQuery Performance Rules
jQuery Performance RulesjQuery Performance Rules
jQuery Performance Rulesnagarajhubli
 
Applications: A Series of States
Applications: A Series of StatesApplications: A Series of States
Applications: A Series of StatesTrek Glowacki
 
Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )Yoshi Sakai
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsMark
 
Architecture, Auth, and Routing with uiRouter
Architecture, Auth, and Routing with uiRouterArchitecture, Auth, and Routing with uiRouter
Architecture, Auth, and Routing with uiRouterChristopher Caplinger
 

La actualidad más candente (19)

Templates
TemplatesTemplates
Templates
 
Angular JS blog tutorial
Angular JS blog tutorialAngular JS blog tutorial
Angular JS blog tutorial
 
Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modules
 
Presentation.Key
Presentation.KeyPresentation.Key
Presentation.Key
 
Silex Cheat Sheet
Silex Cheat SheetSilex Cheat Sheet
Silex Cheat Sheet
 
SharePoint and jQuery Essentials
SharePoint and jQuery EssentialsSharePoint and jQuery Essentials
SharePoint and jQuery Essentials
 
Why I Love JSX!
Why I Love JSX!Why I Love JSX!
Why I Love JSX!
 
UI-Router
UI-RouterUI-Router
UI-Router
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
How routing works in angular js
How routing works in angular jsHow routing works in angular js
How routing works in angular js
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Resource and view
Resource and viewResource and view
Resource and view
 
Rails MVC by Sergiy Koshovyi
Rails MVC by Sergiy KoshovyiRails MVC by Sergiy Koshovyi
Rails MVC by Sergiy Koshovyi
 
jQuery Performance Rules
jQuery Performance RulesjQuery Performance Rules
jQuery Performance Rules
 
Applications: A Series of States
Applications: A Series of StatesApplications: A Series of States
Applications: A Series of States
 
Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )Paypal REST api ( Japanese version )
Paypal REST api ( Japanese version )
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
AngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.jsAngularJS vs. Ember.js vs. Backbone.js
AngularJS vs. Ember.js vs. Backbone.js
 
Architecture, Auth, and Routing with uiRouter
Architecture, Auth, and Routing with uiRouterArchitecture, Auth, and Routing with uiRouter
Architecture, Auth, and Routing with uiRouter
 

Similar a Single Page Web Apps with Backbone.js and Rails

Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 
Javascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & TricksJavascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & TricksHjörtur Hilmarsson
 
Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8Ovadiah Myrgorod
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js FundamentalsMark
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Introduction to Ember
Introduction to EmberIntroduction to Ember
Introduction to EmberSmartLogic
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
Laravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleLaravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleKaty Slemon
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasminePaulo Ragonha
 
MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)Chris Clarke
 
Working with Javascript in Rails
Working with Javascript in RailsWorking with Javascript in Rails
Working with Javascript in RailsSeungkyun Nam
 
EmberJS BucharestJS
EmberJS BucharestJSEmberJS BucharestJS
EmberJS BucharestJSRemus Rusanu
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 

Similar a Single Page Web Apps with Backbone.js and Rails (20)

Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Javascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & TricksJavascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & Tricks
 
Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8Using Backbone.js with Drupal 7 and 8
Using Backbone.js with Drupal 7 and 8
 
Backbone js-slides
Backbone js-slidesBackbone js-slides
Backbone js-slides
 
Angular.js Fundamentals
Angular.js FundamentalsAngular.js Fundamentals
Angular.js Fundamentals
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Introduction to Ember
Introduction to EmberIntroduction to Ember
Introduction to Ember
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
AngularJS.part1
AngularJS.part1AngularJS.part1
AngularJS.part1
 
Laravel 8 export data as excel file with example
Laravel 8 export data as excel file with exampleLaravel 8 export data as excel file with example
Laravel 8 export data as excel file with example
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)
 
Working with Javascript in Rails
Working with Javascript in RailsWorking with Javascript in Rails
Working with Javascript in Rails
 
EmberJS BucharestJS
EmberJS BucharestJSEmberJS BucharestJS
EmberJS BucharestJS
 
Angularjs
AngularjsAngularjs
Angularjs
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
Get AngularJS Started!
Get AngularJS Started!Get AngularJS Started!
Get AngularJS Started!
 

Último

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 

Último (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 

Single Page Web Apps with Backbone.js and Rails

  • 1. SINGLE PAGE APPS WITH BACKBONE.JS & RAILS Prateek Dayal SupportBee.com
  • 2. HOW I LEARNED TO STOP WORRYING AND LOVE JAVSCRIPT!
  • 3. BUT I LOVE JQUERY!
  • 4. VANILLA JQUERY IS GREAT FOR A SIMPLE WEBSITE
  • 5. BUT YOU WANT TO BUILD A SINGLE PAGE APPLICATION
  • 6.
  • 7. Unless you’re a really fastidious coder, some sort of library to help structure large-scale JavaScript applications is important -- it’s far too easy to degenerate into nested piles of jQuery callbacks, all tied to concrete DOM elements. Jeremy Ashkenas
  • 8. ;)
  • 10.
  • 11. • All of the client logic in Javascript
  • 12. • All of the client logic in Javascript • Updates to many parts of the UI on changes to data
  • 13. • All of the client logic in Javascript • Updates to many parts of the UI on changes to data • Templating on the client side
  • 14. TO NOT GO CRAZY BUILDING IT, YOU NEED
  • 15.
  • 16. •A MVC like pattern to keep the code clean
  • 17. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements
  • 18. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks
  • 19. •A MVC like pattern to keep the code clean •Atemplating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks •A way to preserver browser’s back button
  • 20. •A MVC like pattern to keep the code clean •A templating language like HAML/ERB to easily render view elements •A better way to manage events and callbacks •A way to preserver browser’s back button • Easy Testing :)
  • 26.
  • 27.
  • 28. • 3.9 kb packed and gzipped
  • 29. • 3.9 kb packed and gzipped • Only dependency is underscore.js
  • 30. • 3.9 kb packed and gzipped • Only dependency is underscore.js • You need jQuery or Zepto for Ajax
  • 31. • 3.9 kb packed and gzipped • Only dependency is underscore.js • You need jQuery or Zepto for Ajax • Annotated source code
  • 32. MVC
  • 33. MODELS, VIEWS & COLLECTIONS
  • 34.
  • 36. MODELS • Data is represented as Models
  • 37. MODELS • Data is represented as Models • Can be Created, Validated, Destroyed & Persisted on Server
  • 38. MODELS • Data is represented as Models • Can be Created, Validated, Destroyed & Persisted on Server • Attribute changes trigger a ‘change’ event
  • 39. SB.Models.TicketSummary = Backbone.Model.extend({ id: null, subject: null, name: 'ticket', });
  • 41. COLLECTIONS •A collection of models
  • 42. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh
  • 43. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh • Can fetch models from a given url
  • 44. COLLECTIONS •A collection of models • Triggers events like add/remove/refresh • Can fetch models from a given url • Can keep the models sorted if you define a comparator function
  • 45. SB.Collections.TicketList = Backbone.Collection.extend({ model: SB.Models.TicketSummary, url: "/tickets", name: "tickets", initialize: function(models, options){ // Init stuff if you want } });
  • 46. VIEWS
  • 47. VIEWS • They are more like Rails’ Controllers
  • 48. VIEWS • They are more like Rails’ Controllers • Responsiblefor instantiating Collections and binding events that update the UI
  • 49. SB.Views.TicketListView = Backbone.View.extend({ tagName: 'ul', initialize: function(){ this.ticketList = new SB.Collections.TicketList; _.bindAll(this, 'addOne', 'addAll'); this.ticketList.bind('add', this.addOne); this.ticketList.bind('refresh', this.addAll); this.ticketList.bind('all', this.render); this.ticketList.fetch(); }, addAll: function(){ this.ticketList.each(this.addOne); }, addOne: function(ticket){ var view = new SB.Views.TicketSummaryView({model:ticket}); $(this.el).append(view.render().el); } });
  • 50. SB.Views.TicketSummary = Backbone.View.extend({ initialize: function(){ _.bind(this, 'render'); if(this.model !== undefined){ this.model.view = this; } }, events: { 'click': 'openTicket' }, openTicket: function(){ window.location = "#ticket/" + this.model.id; }, render: function(){ $(this.el).html(SB.Views.Templates['tickets/summary'] (this.model.toJSON())); return this; } });
  • 52. {{#ticket}} <div class="listing-cell name"> <p>{{nameOrEmail requester}} ({{replies_count}})</p> </div> <div class="listing-cell subject"> <a href="#{{id}}"> {{#unread}} <b>{{subject}}</b> {{/unread}} {{^unread}} {{subject}} {{/unread}} </a> </div> {{/ticket}}
  • 53. URLS
  • 54. URLS • Collections can have a url
  • 55. URLS • Collections can have a url • Models can have a url or they can derive it from collection’s url
  • 56. create → POST   /collection ◦ read → GET   /collection[/id] ◦ update → PUT   /collection/id ◦ delete → DELETE   /collection/id
  • 58.
  • 59. • Used for setting up the routes
  • 60. • Used for setting up the routes • You can add new routes during runtime
  • 61. SB.Controllers.AgentHome = Backbone.Controller.extend({ routes: { "": "dashboard", // http://app_url ":id": "openTicket" // http://app_url#id }, dashboard: function(){ var view = new SB.Views.TicketListView; $("#ticket").hide(); $("#list").html(view.el); $("#list").show(); }, openTicket: function(id){ var view = new SB.Views.TicketView({model : new SB.Models.Ticket({id : id})}); $("#list").hide(); $("#ticket").html(view.el); $("#ticket").show(); } });
  • 62. window.controller = new SB.Controllers.AgentHome
  • 63.
  • 64. • Initiates a new controller instance
  • 65. • Initiates a new controller instance • which matches the dashboard route
  • 66. • Initiates a new controller instance • which matches the dashboard route • and creates a instance of TicketListView
  • 67. • Initiates a new controller instance • which matches the dashboard route • and creates a instance of TicketListView • and a TicketList collection is created
  • 68.
  • 69. • TicketList collection fetches tickets and triggers the refresh event
  • 70. • TicketList collection fetches tickets and triggers the refresh event • Refresh handler renders a TicketSummary view for each ticket and adds it to the top level element
  • 71.
  • 72. • Every Ticket Summary row has an onclick handler
  • 73. • Every Ticket Summary row has an onclick handler • which changes to url to #ticket_id
  • 74. • Every Ticket Summary row has an onclick handler • which changes to url to #ticket_id • which matches the openTicket route
  • 77.
  • 78. • Youcan use as_json to customize the json responses
  • 79. • Youcan use as_json to customize the json responses • Or you can use Restfulie
  • 80. • Youcan use as_json to customize the json responses • Or you can use Restfulie • Restfulie lets you easily put links in representations too
  • 81. collection(@items, :root => "items") do |items| items.link "self", items_url items.members do |m, item| m.link :self, item_url(item) m.values { |values| values.name item.name } end end
  • 82. NOT JUST FOR API BACKED MODELS
  • 83. //window.AgentHomeController = new SB.Controllers.AgentHome; window.mainView = new SB.Views.Main; mainView.screens.add(new SB.Models.Screen({ title: 'Dashboard', href: '#dashboard', listings: [ { title: 'New Tickets', url: '/tickets?label=unanswered&replies=false' }, { title: 'Ongoing Tickets', url: '/tickets?label=unanswered&replies=true' }, { title: 'Starred Tickets', url: '/tickets?starred=true' } ] }));
  • 86. beforeEach(function(){ var ticket = new SB.Models.TicketSummary({id: 1, subject: "A Ticket", replies_count: 0, requester: {id : 1, email: 'requester@example.com', name: 'Requester', thumbnail: 'thumbnail-url'} }); this.view = new SB.Views.TicketSummary({model: ticket}); this.view.render(); }); it("should render a ticket summary correctly", function(){ expect($(this.view.el)).toHaveText(/A Ticket/); expect($(this.view.el)).toHaveText(/Requester/); }); it("should change the url on click", function(){ var currentLoc = window.location.toString(); $(this.view.el).click(); expect(window.location.toString()).toBe(currentLoc + "ticket#1"); });
  • 88. beforeEach(function(){ this.server = sinon.fakeServer.create(); this.server.respondWith("GET", "/tickets_url_mock_server", [200, { "Content-Type": "application/json" }, '{"tickets":[{"id": 1, "subject": "Ticket 1"},{"id": 2, "subject": "Ticket 2"}]}' ]); }); it("should instantiate view when tickets are fetched", function(){ var viewMock = sinon.mock(SB.Views); viewMock.expects("TicketSummary").once().returns(new Backbone.View); viewMock.expects("TicketSummary").once().returns(new Backbone.View); var view = new SB.Views.TicketList({url: "/tickets_url_mock_server"}); this.server.respond(); viewMock.verify(); expect($(view.render().el).children().length).toBe(2); });
  • 89. QUESTIONS? prateek@supportbee.com @prateekdayal http://supportbee.com

Notas del editor

  1. Prateek Dayal, 4 years with Ruby on Rails, CoFounder SupportBee, A help desk Software for SME, like the ones using Basecamp, Also did Muziboo and run HackerStreet .. Will be talking about ... how many of you love js?\n
  2. As Douglas Crockford puts it, most widely installed language but most misunderstood or not understood at all. A lot of care for Rails but not so much for JS etc\n
  3. How many of you have used jQuery?\n
  4. If you have to select a few elements and show/hide them or apply a css property etc\n
  5. Something like Gmail. Incoming Emails affect multiple items in the view etc. \n
  6. \n
  7. Choosing a framework is like choosing Ruby on Rails. It gives you a set of conventions and a place to put things. A lot of good choices have been already made for you. \n
  8. Most of this talk is based on our experience of building SupportBee, The ticketing page is a single page app like gmail. The code is from SB\n
  9. \n
  10. Only communicate data with the server after being loaded. \n
  11. Only communicate data with the server after being loaded. \n
  12. Only communicate data with the server after being loaded. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. Created by Charles Jolley, Used in Mobile Me, iWork.com, In Strobe Inc\n
  21. Created by the founders of 280 North Inc. Used in GoMockingBird, Github Issues\n
  22. \n
  23. \n
  24. Done by Jeremy Ashkenas. He has also created coffeescript and jammit. Jammit and Backbone is part of the document cloud code. Basecamp mobile is built using Backbone\n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. You get a json of tickets and display it. And on clicking the ticket the url should be changed and ticket should be displayed\n
  32. \n
  33. \n
  34. \n
  35. Unlike a Rails&amp;#x2019; model, there is no inbuilt support for Associations yet\nYou can initialize values in the initialize method\nextend helps you setup the prototype chain so that you can again inherit from this model\n
  36. \n
  37. \n
  38. \n
  39. \n
  40. This is a collection of model SB.Models.TicketSummary\n
  41. \n
  42. \n
  43. Views also instantiate other views, which can render templates\n
  44. Event binding for click happens here\nRenders a handlebars&amp;#x2019; template\nThe model stores a reference to this view. This reference can be used to remove/update view on changes to the attribute\n
  45. \n
  46. Logicless template. Simple JSON parsing and if/else\nnameOrEmail is a helper function that you can register\n
  47. \n
  48. \n
  49. Models inherit their urls from collections. For example\n
  50. \n
  51. \n
  52. \n
  53. The openTicket route will be fired when the ticket is clicked\n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. The controller has already appended the top level element to the list element on the page and has made it visible. So when tickets are populated, they show up on the page\n
  60. The controller has already appended the top level element to the list element on the page and has made it visible. So when tickets are populated, they show up on the page\n
  61. \n
  62. \n
  63. \n
  64. \n
  65. Though you can keep this and add some parsing code to parse the json out on client side\n
  66. \n
  67. \n
  68. \n
  69. Look at Rest in Practice or Roy Fielding&amp;#x2019;s blog for more info\n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n