Jasmine
Backbone.js, Jasmine and Rails: The Lust Story
Summarized using AI

Backbone.js, Jasmine and Rails: The Lust Story

by Austin Fonacier

Introduction

In this presentation at LA RubyConf 2013, Austin Fonacier, a senior software engineer at Spoko, discusses the integration of Backbone.js, Jasmine, and Rails in web development, specifically focusing on a project called Blog Mate. Austin emphasizes the importance of Backbone.js for creating a cleaner, more organized codebase and improving testing.

Key Points

  • Background Information: Austin shares his experience and highlights his collaboration with Danny on Blog Mate, a project utilizing Rails, Backbone, and Jasmine. He notes his self-proclaimed limitations in JavaScript and Ruby expertise but aims to share his practical experiences.

  • Framework Overview: Austin provides a brief overview of the frameworks:

    • Rails: A Ruby-based MVC framework known for its test-driven development (TDD) and RESTful principles.
    • Jasmine: A behavior-driven development (BDD) framework for testing JavaScript code, resembling RSpec in functionality.
    • Backbone.js: A lightweight JavaScript framework that structures client-side applications, offering models, views, and simplified routing for single-page applications (SPAs).
  • Project Challenges: The team initially faced issues with their JavaScript code, which was becoming unmanageable with bloated files filled with inline jQuery. They noted complications with handling views and ensuring changes in models reflected accurately across the application.

  • Team's Transition to Backbone: Austin explains the decision to adopt Backbone.js after encountering difficulties in maintaining modular and clean code. Backbone's structure allowed them to define dedicated JavaScript classes for each model and view, promoting better organization and interaction.

  • Implementation Details: The talk includes code examples demonstrating the use of Backbone for managing models and views, such as how the save functionality mimics ActiveRecord and how views are structured to handle dynamic frontend updates.

  • Benefits Realized: With Backbone, Austin's team achieved:

    • Modularized JavaScript, leading to a cleaner codebase and improved performance.
    • Built-in validation and helper methods, facilitating efficient model management.
    • Enhanced flexibility in view management, allowing them to structure applications efficiently while handling routes seamlessly.
  • Unit Testing with Jasmine: Austin highlights the critical role of Jasmine in implementing unit tests, helping to avoid issues associated with alert-driven development, further ensuring code integrity.

Conclusion

Austin concludes by reaffirming the effectiveness of Backbone.js as a framework that offers organizational benefits, streamlining development processes and fostering better project stability. He encourages attendees to consider utilizing Backbone in their future projects for cleaner architecture and improved testability.

Takeaways

  • Backbone.js enhances code organization and flexibility in JavaScript applications.
  • Jasmine is crucial for ensuring code reliability through effective testing practices.
  • Continuous learning and adaptation of frameworks can significantly improve development workflows.
00:00:24.160 Austin is a senior software engineer at Spoko here in Los Angeles. At one point in time, he worked for what is now YP, which used to be AT&T Interactive Yellow Pages. We worked together at YP in a previous iteration of work. I'm going to go ahead and let him talk to you about Rails, Backbone.js, and Jasmine.
00:00:51.160 Hello, cool! My slides won't take up the full time, so I know there's been a lot of learning here lately. I just wanted to tell a personal story.
00:01:12.880 Like Corey, I have a cat, and that's why I enjoyed this presentation. I haven't followed Corey yet on Twitter, but I definitely will now because of the cats! I have a cat named Pam Beasley, and I love her to death. I love Pam more than I love most humans, which is saying a lot. When I first got her, I had never had a cat or dog before.
00:01:37.600 Essentially, I used to take her on supervised walks outside. I subscribed to the idea that if you have a cat or dog off-leash, they're just going to take off and run. So I closely monitored our outdoor walks, taking her out on the balcony or just in front of my apartment complex.
00:01:58.399 One time, she escaped. I literally looked away for a second, and she was on the back gate of my apartment complex, straddling that gate. I couldn't believe it. My girlfriend and I quickly ran into the apartment to grab her favorite toys to coax her down, saying, "Hey Pam, come down!" But she wouldn't listen and just jumped over to the other side.
00:02:14.400 I had no idea what was on the other side because it was a brick fence. I quickly calculated my options: maybe she would come back, and maybe she wouldn't, but I decided to go after her. I hopped over the wall and found her chilling in the sun. I couldn't believe it! I grabbed her, but she freaked out and scratched me while I yelled to my girlfriend.
00:02:35.840 It turned out the other side of that wall was someone's backyard. I was essentially breaking and entering to get my cat back. I yelled to Denise, my girlfriend, asking if I should climb the wall, but she said it was a dumb idea and that she wouldn't catch my cat if I threw her over. From the front yard, I heard someone yelling, "Get off my lawn!" I thought I was going to jail for trying to rescue my cat.
00:03:00.280 So I explained to this lady that my cat ran away, and she surprisingly said it was no problem. There I was, walking around the block to bring my cat back home. That's my Pam story.
00:03:51.200 At every conference, you come back home and get asked how it was. You usually say all the presentations were awesome except for one—that's me. So, I apologize in advance for that. Basically, I have a side project called Blog Mate. It's written in Rails, Backbone, and a bit of Jasmine. I want to share how it came to be, why we used Backbone, and the end product we achieved.
00:04:11.360 A quick intro about myself again: I'm Austin, and I work at Spoko, based in Pasadena as a software architect. This is a drawing of me and Blog Mate, which consists of three people. On the left is Ben, the middle is me, and on the right is Danny. Danny and I write most of the code, and yes, Danny does dress like that every day—it's pretty crazy!
00:04:38.639 As a precursor, I'm not a JavaScript expert, so if you guys ask crazy questions at the end of the talk, I may not be able to answer them properly. Likewise, I'm not a Ruby or Rails expert, so again, if you have questions, I probably won't have the answers. I'm just a decent user of the existing tools out there, and I'm here to share my experiences, the thought process of how we came to use these tools, and the end product of using them.
00:05:04.479 Lastly, all JavaScript examples are in CoffeeScript. If you don't write CoffeeScript, I highly recommend it. One portion that we used on Blog Mate is Rails. This is a Ruby conference, so we've all heard of it—it's a Ruby-based MVC framework. It's very test-driven development (TDD) driven and RESTful.
00:05:30.800 Next is Jasmine. Jasmine is a behavior-driven development (BDD) framework for testing JavaScript. It is really nifty! It looks like RSpec. If you look at Jasmine, you will see RSpec; likewise, if you look at RSpec, you'll see Jasmine. It also integrates with Selenium or whatever continuous integration (CI) environment you have through the Jasmine gem that is available.
00:05:56.000 Lastly, I want to talk about Backbone. Backbone is a JavaScript framework used in the front end. It has models and views but lacks controllers. For those who have used Backbone, views ride the line between views and controllers, so they are somewhat simultaneous. Backbone also has a concept of routes for single-page applications.
00:06:10.400 It's a small library at just 6 kilobytes, so there's minimal overhead. The only hard dependency is Underscore, which functions like a utility belt for JavaScript—providing functions like `each`, `filter`, and more that Backbone uses for various nifty features. Lastly, Backbone is template-agnostic, meaning you can bring your own templates. On Blog Mate, we use Smarty templates, but everyone has their own preferences.
00:07:00.199 In the early days of writing Blog Mate, many projects began with built-in Rails helpers, such as link to remote or form remote tags, which effectively wrote the JavaScript inline, making the code difficult to manage as the project matured. As the product began to grow, it eventually reached a point where we had a bloated application JS file full of plain jQuery that simply exploded.
00:07:31.680 Danny and I sat down and decided that we wanted to avoid that scenario. We really liked the asset pipeline that Rails offers, so we aimed to modularize everything. Every view in Blog Mate has a dedicated JavaScript class, and likewise, every model represented on the front end has a corresponding JavaScript class representing that model.
00:07:51.240 Now, enough with the bullet points. Let’s get into it! Here is a representation of the model before Backbone. In this code, you can see the constructor where attributes are passed in and assigned to the class. The save functionality tries to mimic ActiveRecord as closely as possible.
00:08:04.820 The save method takes the attributes and performs a jQuery call. If the model has an ID, it treats it as an update and makes the appropriate server call. Additionally, we implement callbacks for after update and after create, which take the attributes returned from the server and assign them back to the model. It seems simple enough!
00:08:22.960 Next, here’s an example of a view for an article. We pass in an article model, cache elements, bind components to the page, and render when necessary. Interestingly, Danny wrote this, and it looks almost exactly like Backbone. The patterns he created were remarkably similar to how Backbone handles its views.
00:08:39.360 When we wrote our first version of JavaScript, it was awesome! We thought we were hot stuff, imagine programmers high-fiving each other. We've never been on a project that had modularized JavaScript that was clean and worked as intended; it was exhilarating!
00:08:51.360 Everything was organized, everything was objectified, and everything just worked! However, we soon realized maybe we weren't the greatest programmers ever, which made us a little disheartened.
00:09:11.680 One of the challenges we faced was in the view—we wanted to handle actions after saving. It made sense: after you create a new list, you want to call the Smarty template and pass the list attributes to it for appending to the DOM. If the list was saved, it would append the template to the view.
00:09:31.360 Here’s how the model functions relate to that. Remember, the save method takes the attributes, makes a jQuery call, and after create, it passes the ID back into the model. The issue arose because, in development, everything worked like a charm. However, in non-development environments, we faced a different scenario.
00:09:54.200 In production, our views did not tap into the model save callbacks. When creating or updating, the model expected to pass back its ID. This ID was crucial for the Smarty template that needed the ID for routing and rendering.
00:10:06.360 We were baffled as to why the Smarty template wasn't functioning correctly. Our model may not have received the ID back from the server before rendering the template, leading to broken links upon refreshing the page.
00:10:20.840 The view would try to render a template without an ID, which disrupted everything. We found ourselves asking, 'Why is our Smarty template giving issues?' This was one of the major questions we faced!
00:10:35.280 Another problem arose as our application grew with multiple view classes in a single HAML view. This architecture meant that updating multiple views based on a single model's save, update, or destroy actions became quite confusing.
00:10:45.920 For instance, when a new list was created, it may be represented across many views, making changes complex. We had to ensure that we updated each view's representation appropriately when actions occurred on the model.
00:11:10.520 You can visualize it like this: if I wanted to delete the top article in a list, I had to update multiple views to reflect that change. We struggled to manage this aspect of our architecture.
00:11:25.360 This challenge highlighted a significant insight—if a model was destroyed, we didn’t have a robust mechanism to determine if the view should also remove the article. It was essential to listen and tap into the model's callbacks effectively. The same holds true for update scenarios.
00:11:44.000 Imagine trying to save a change and discovering the server response indicated a problem, like an insufficient length for a list name. The view was unaware of this because it wasn’t hooked into that callback process.
00:12:04.800 Our initial brainstorming included passing views into models, enabling the model to trigger updates in views when changes occurred. Yet, we quickly dismissed this as it would create an overly tangled web of code. Instead, it ended up leading us to adopt Backbone.
00:12:15.440 Here's an example of a Backbone view directly pulled from Backbone.js documentation. You specify default attributes such as tag name or class name, and then you bind events for DOM interactions. Rendering occurs by creating elements based on these attributes, eliminating redundant JavaScript code.
00:12:39.000 For instance, this document row example allows for efficient creation of HTML elements specified in the Backbone view. It saves time by leveraging predefined attributes. You don’t have to repeatedly write code to create elements because Backbone automatically handles this for you.
00:12:59.600 Now, let's look at this loader class we created. We use it when performing long calculations on the back end, so we can show a loading bar on the front end during those processes. The view for this simply includes a loading indicator that continuously loads until the task is complete.
00:13:14.320 Here’s a view implementation on Blog Mate’s top view. This section demonstrates how list views are structured, including default options like tag names and templates. This allows for the creation of dynamic Frontend components that reset with every model’s change.
00:13:29.120 Views in Backbone are very flexible. I’ve presented different ways of organizing views, and the framework allows you to mold it according to your needs, making it an excellent resource.
00:14:08.039 Additionally, Backbone offers route management. Each view has a corresponding route, allowing seamless functionality as your application grows. As we advanced our application, we started creating views for each page.
00:14:30.760 Consequently, we structured our application to use global app views effectively, implementing subviews as needed for partials across the application. This approach allowed us to use views with very low overhead.
00:15:06.359 Backbone models resemble ActiveRecord in functionality. They expect JSON from the backend and provide populated models in return. Essentially, Backbone's models enable easy interaction with RESTful backends, allowing seamless integration with existing Rails applications.
00:15:29.440 This meant that once we migrated over to Backbone models, we could delete a ton of redundant code, resulting in a leaner codebase with better organization.
00:15:41.600 Backbone also includes built-in validation, making it easy to manage simple rules for the models. Furthermore, it provides numerous helper methods that enhance the effectiveness of our development process.
00:15:56.800 The routes in Backbone mirror some of the familiar patterns from Rails applications, enabling smooth transitions when structuring single page applications. This approach reduces unnecessary page refreshes, delivering a more fluid user experience.
00:16:10.640 In conclusion, Backbone serves more as a foundation rather than a full-fledged framework. If you had asked me a year ago, I might have suggested using Backbone solely in applications where you constantly push and pull models from the backend to the frontend.
00:16:25.270 However, its minimal overhead and effective organization helped us re-evaluate our approach. We began implementing Backbone across all our projects at Spoko since its implementation simplified our overall code organization.
00:16:39.279 In addition to its organizational capabilities, Backbone views are incredibly versatile. They allow developers to choose their path without strictly enforcing a single implementation model, providing flexibility for creativity.
00:16:54.960 The events module served as a lifesaver, since multiple views could independently interact with corresponding models. By subscribing to the events emitted by models, views were kept decoupled but maintained efficiency.
00:17:10.319 Ultimately, we were drawn to Backbone for events but stayed for the overall organizational benefits. It saved us time, reduced the amount of code written, and made our projects run smoother!
00:17:26.160 While learning Backbone, we realized the importance of Jasmine for unit testing. We aimed to avoid alert-driven development, which can be problematic when hidden alerts pop up in the code.
00:17:41.919 We intend to upload these slides to GitHub, along with updates related to routing as we gather more information. Also, I’ll share resources that have been incredibly helpful as we learned about Backbone.
Explore all talks recorded at LA RubyConf 2013
+6