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.