TDD Your JavaScript With Backbone.js w/Mike Jansen

UGtastic Archive
Full Transcript Available 73 Minutes
LIVE CC UGtastic Archive

Press play or click any turn in the transcript to start real-time synchronized playback...

Take control of your client Javascript code by TDD'ing with Backbone.js. We'll cover how to use Backbone.js in your next project as well as patterns for testing your Javascript effectively.
The Interviewer

Mike Hall

Interviewer, UGtastic

The Guest

Guest

Guest

The Conversation


Guest Guest ▶ Speaking
...way to really write good code that I'm proud of. You end up with a form that's normally HTML, and then you want to add some hiding or showing of one of the fields, and then you put something in the document ready, and then you hide it on one case, and then something happens, and then it changes, and it doesn't really feel right. I'm not sure how to test that. I'm not sure how to control how that works without some, you know, some web-based tests that don't make me very happy. So, I started using Backbone about four or five months ago. I was working with a client, and they were about to embark on a new project that they knew was gonna be client-side heavy. They had made a mess in their previous application with their JavaScript and wanted to get a better control over what this new code was gonna look like. And so they started looking at a few options. They were looking at, I think, JavaScript MVC was one, Sprout Core was another, and Backbone.js. Spent some time specking things out, and for us, we ended up succeeding the best in that short amount of time with Backbone.js. It was just kind of an easier learning curve. Kind of felt like you were writing JavaScript and not really learning another set of, another language to write what your JavaScript should do. So we embarked with Backbone. I learned a lot about how to write with Backbone, how to test with Backbone, and have come up with some patterns, some ideas about what good Backbone.js code looks like, how it should all work together, and that's what I'm gonna cover today. We're gonna talk first about Backbone.js, so I wanna give a good intro to what the framework is like, and then we can start to dive in how you would use Backbone in a web project or how you would evolve your project using tests in order to add that functionality bit by bit.
Guest Guest ▶ Speaking
So, that being said, let's just stop and talk about JavaScript right away. JavaScript is an interesting language. It's kind of a bit like Frankenstein, in that it's kind of, it was kind of cobbled together, right? It's not a lot of standards in there. It's really powerful, though. It's really fast, and it's got all these standards that are used all over the place. I mean, all the browsers are supported, but it can also kind of rip your arms off if you're not careful, and it can cause a lot of problems. So it's kind of up to you to control JavaScript. You want to kind of get away from just this procedural mess of code that happens in your document-ready, and actually just get a grip on it. Make sure that it's doing what you want it to do and not having it override something that lives in the global namespace.
Guest Guest ▶ Speaking
So, back to Backbone.js. A little bit of background on the creator. Jeremy Ashkenas is the guy that, he worked at a company called Document Cloud. It was a project that was JavaScript heavy, and out of their experience with Document Cloud, they ended up creating and extracting out Backbone.js. Jeremy also is the creator of CoffeeScript. I don't know if any of you folks have used CoffeeScript before, but he's done those two things. And also Underscore.js, kind of a collection of functional-type methods that you can use with your JavaScript projects. So, when it comes down to Backbone, it's really about structure. The structure that it can give to your application. One of the examples here is, there's a model in Backbone. Backbone is kind of built as an MVC framework for the client side. I'm not sure if that's entirely accurate, but it does have structure. It's got a framework, and it's got a model in it. We'll leave the discussion of whether it's a true MVC for another time. But here's an example of how a model works. How you set up a model. So, you set up a task. This is a pretty straightforward task model. You can have defaults. So, if you create a new instance of a task, it will have this attribute of complete, and it's gotta be false. You can also create, so if you create it, you can give it other values. So, you can give it a description. And then when you call task.getDescription, it's gonna return that value to you. Models can live inside of collections. Collections are really just kind of a convenient way to access a group of models. So you've got some defaults. So, you can say, if you want to create something through a collection, you can pass in the list of attributes, and it's gonna create an instance of that model that's been associated with it, with those attributes.
Mike Hall Interviewer, UGtastic ▶ Speaking
Can you go just a little slower through that?
Guest Guest ▶ Speaking
Sure, sure. Uh, so yeah, just to back up here on the collection, I can talk a little about how this interacts with the server, too. So, models and collections are gonna represent the data that lives in your server. It's not gonna live in the client. It's gonna live somewhere else. And in some of the apps I passed around, it can live in a Rails project. It can just be HTML5 local storage. Just somewhere that you're gonna get the data from to display to your user. So in this case here, you've got, you're extending the Backbone collection base object, and adding a couple attributes to it. The model that's listed here is just a namespace. This is the application namespace of to-do. This is my models underneath it, and this is the task. That's essentially what the model definition is. And then the URL there is tasks. And so the URL is going to be the action that it tries to access whenever you do a save or a create or a destroy on the model. And those are gonna just correspond to the right HTTP request to get a new one, to fetch out an entire index of these models, to update them, to destroy them. So that's part of that configuration there on the collection. And back here in this collection example, we instantiate the task collection, and then we're calling a create, and that's going to add models. Instances of models to the collection. And also take care of sending that post request down to the server to actually create and persist in the database. Any questions? Okay.
Guest Guest ▶ Speaking
One of the nice things about Backbone is that you don't have to use the entire framework. You can kind of pick and choose what you want to interact with when it comes to the objects. An example of this is the Backbone router. So the router's function in Backbone is to essentially monitor the window location, the URL that you're visiting. When you initialize a router, it's going to take these actions. You can use it to kind of bootstrap in any values that you load from your initial server request. So say you're serving up an HTML page, and you're going to give it some data to start with. So you can call this router with these options and say, okay, well, I already have some tasks I've loaded. So I'm just going to create that inside of this router. And I'm also going to create a view that has that collection. We're going to get to views in a second here. And then you can define some routes inside of here. So that empty string there is going to be the default route for the page. And then it's going to call that function when it hits that route. So if you go to the base URL of the page, the first thing it's going to do is call this load task function. And that's going to go off and probably load some tasks, right? And then if you visit a URL that looks like this, it's with a little slug for the ID there. It's going to fire the edit task function. An example of what the edit task function might look like is this here. So let's say you're just going through your to-do app. You've got a list of things that you want to get done. And you click on one of those tasks. That can act as a link that just directs you to that URL that we specified. And it's going to fire this edit task function. This is going to instantiate a view that we passed along the collection. So it has knowledge of it and then render that view. Again, I'm going to get a little bit more to the views in a second. Well, this is kind of a typical thing. You know, when you hit a URL, it's going to render, it's going to do some action or render something for the user. This is how you'd use a router. So essentially inside of a document ready or somewhere on your page, you're going to instantiate your router. And then in order to actually start the router doing things, you need to start backbone history. Backbone history is going to work if you have a router defined on your page and it's got some routes defined. So assuming you have all that set up that I showed on the previous slides, as soon as you start off the backbone history, then it's going to start monitoring the URLs and start firing actions. So if for some reason you didn't want to start monitoring right away, you could defer that starting of the history monitoring and then start using backbone after you've loaded the page and they've taken some action.
Mike Hall Interviewer, UGtastic ▶ Speaking
Do you have any insight into why it's history? It seems like a weird thing to call it.
Guest Guest ▶ Speaking
Um, I think it's kind of keeping in parallel with the DOM, like window history inside of a browser. So there's something similar that keeps the history of the browser and everything that you visited. So I think that's what it's trying to parallel.
Mike Hall Interviewer, UGtastic ▶ Speaking
Okay, along with that, is it trying to be, like, a polyfill for HTML5? Yeah, I, I don't know too much about the API, but—
Guest Guest ▶ Speaking
Um, I mean, I think it's trying to get the same idea of, you know, this is the list of things. I'm not necessarily sure, I don't think this requires the HTML5 interface to make it work, but it's kind of the same idea, so we want to have access to this state. So actually, for example, if you clicked on a link to edit a task, right, you're gonna get a URL, it looks like this, your slash to-do, and then the hash with task slash 34 slash edit, and the nice thing about this is, if you instantiate that backbone router on your page, and start monitoring the history, you can essentially link to this permanently. You can pass this around, and when backbone gets loaded, it's gonna find that URL that you gave it, and then load that, so you can actually take a link that you can send to someone, and it's gonna load the JavaScript right away for you. This link actually means something because of backbone, and it can load where you were in the state of that JavaScript versus having to link to a static HTML page. Any questions on the router? Yeah, it's pretty slick. It's a nice way to keep track of things. This convention of using the hash for what the JavaScript portion of your webpage is doing is something that you'll probably see on Twitter, other things, that they're not using backbone, but I think it's kind of the convention that's emerged for trying to store what would be a JavaScript-ish type link. So...
Mike Hall Interviewer, UGtastic ▶ Speaking
Oh, I'm sorry. Yeah. So, another question is, along with that, I've heard some backlash for using, like, the hash just because, you know, everything after the hash doesn't get sent down to the server, and now you're kind of stuck with links with hashes, you have to maintain that all on the client side. Yeah. Is there, like, an option not to do that? So, like, if the browser does support HTML5 history, then it can do that? Or is it just hard coding just to do the hash?
Guest Guest ▶ Speaking
Um, it is, you may be able to overwrite it. I'm not sure if it's going to be the hash specifically, or if it's going to detect something or other. You know, what I found — we'll probably talk about this more at the end of it, too — is I found that with a lot of these JavaScript frameworks that are emerging, they're kind of just saying, "That's to IE7 and below. We're just going to support the new stuff." Because it's too hard. Excuse me, it's too hard. And it's easier to support the browser that actually can render JavaScript in a reasonable manner, a more predictable manner, you might say.
Mike Hall Interviewer, UGtastic ▶ Speaking
How well does it play with other libraries that use hash as well?
Guest Guest ▶ Speaking
Mm-hmm.
Mike Hall Interviewer, UGtastic ▶ Speaking
Like, is it going to be a problem? I believe that jQuery mobile uses the hash as well?
Guest Guest ▶ Speaking
Um.
Mike Hall Interviewer, UGtastic ▶ Speaking
So would you, I don't know, would you ever try to use both in an application?
Guest Guest ▶ Speaking
Uh, you know, I mean, I've heard of some projects that are trying to use Backbone and jQuery mobile UI. I haven't taken a look at it specifically, but yeah, I mean, that's definitely something you'd have to be aware of is how all your different libraries can interact with it. You know, the nice thing about the router is that if your application doesn't really require you to jump back to a certain state, this is the part I like about Backbone is you don't have to use it. It doesn't fire it up for you to start with, you can just not create a router and have the functions that render stuff just happen from event bindings. So that's one way to get around is just to not use that function if you don't want to. I imagine though, if there was another library that was waiting for the window history to change and detect some hash, it could be that both actions are triggered. It could do the thing that one JavaScript library is waiting for the event on of the certain history state. And then also Backbone is going to execute, and then whatever happens is anyone's guess at that point. I guess it depends on what it does to the DOM, who wins, who gets there first.
Guest Guest ▶ Speaking
So speaking of the DOM, things have been pretty good until now, right? We're just talking about stuff on the server, monitoring the window's history state. This has all been pretty straightforward. Pretty simple structure. There's not a lot of complexity yet, but when it comes to the DOM, you enter into this really murky territory. You've got some control over what's in there, if you're the one creating the full application, but if you're working with someone else that's giving you HTML, it can get a little tricky. And it certainly behaves differently across browsers as well. So let's talk more about the views in Backbone. So this quote here is actually from the Backbone.js documentation. They're more convention than code, and that's certainly an accurate description. Now when I talk about a Backbone view, I'm really talking about an object, something that's going to control a certain slice of the DOM. Something that's going to watch a certain element on the page that you give it and it's going to bind events to it. It's going to render things inside of it. And that's the convention part. I mean, that's what you want it to focus in on one part of the DOM, even though you can still access and do anything else you want inside of it.
Guest Guest ▶ Speaking
Uh, should we take a two minute break to grab pizza?
Mike Hall Interviewer, UGtastic ▶ Speaking
Yeah.
Guest Guest ▶ Speaking
Before I dive into how the view looks as an object, why don't you guys grab some slices of pizza and we can start back up here.
Guest Guest ▶ Speaking
Short of the... Yeah. That's what I hear, uh, what's that? I hear. Yeah. More of a type of picture, but I couldn't find you. I was just, uh, here. I was just a drink. Yeah, there's, top of the basket. The top and the best amount of water. Yeah, right. The angle of water. And if there's a water fountain, it would be nice. Oh, I mean, I see. I have a patient. Yeah. Sorry, I wish you did. Um, yeah, we're happy. Yeah. How's the gym going? It's going? Yeah. So. Oh, there's touch technology right here. There's St. Leighton. Um. Oh. Yeah. Very nice. Oh, are you going to run the computer out? Yeah. Thank you.
Guest Guest ▶ Speaking
All right, looks like everyone's got a slice, at least a slice of pizza, so we can get started back up here. All right, so, getting back to the Backbone views, so let's take a look at what a view might look like. Views, one way to use a view in Backbone is to, in order to define it like you would your other objects, your collections and your routers and your models. And you're gonna give it, one thing you can do is you can give it some tag names and class names. Now, this is just kind of a way of saying, if you want Backbone to render some HTML, these can kind of be your container tags and classes. So, no matter what you render and add to inside the element for that view, it's going to wrap it inside of this. So, another part of it for the view is that a view provides a really nice way to bind events to a part of the element, to a certain element of the DOM. What happens is that this hash of events are just gonna, as soon as you instantiate the view and give it an element that it's gonna manage, to control, it's gonna bind these events to it. And if you remove the view, it's gonna destroy the events. It kind of is a way to push out that knowledge and that maintenance of the event bindings. And there's some convenience methods as well for, if you want to rebind all your events or unbind them, that exists as well.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, like, um, this is kind of like the live method in the older versions of jQuery, in that it does it dynamically, you know, add new graphs to your page, and you have a view out there for whatever you added, it's automatically gonna find it and bind it?
Guest Guest ▶ Speaking
Essentially, yeah, if you render — let me, I can get to it in a second. But so, a view is gonna also render. If you're gonna render HTML and add it to the element that the view is controlling, it's gonna bind events to it. One of the ways that you can use a view is that you can hand it an existing element in your HTML. So, let's say you'd go into static HTML and now you want to control something inside it with Backbone. As soon as you instantiate the view with that element, it's gonna try and bind all those events to it. So, if you've got some static HTML that you're gonna serve it up like that, and you want Backbone to monitor it, whatever's inside of it, it can bind events to that as well. So, it's another way just to kind of take care of that event binding. That's something that I found really convenient about Backbone views. So, for this function here, when a key up occurs on the new task ID selector, we wanna do a function for create on enter. And so, what that function might look like is, you know, when you perceive this key up event, we want to add the input value from the field that we're watching and do a collection create. So, the idea is that, you know, if you're typing something into your to-do app, you hit enter on the field, it's going to add a model to your collection with whatever you just typed in. And I'm omitting some of the code here, but, you know, checking that you're hitting the enter key and not just some random key. But that's kind of the gut stuff. That's what the Backbone part of it is.
Mike Hall Interviewer, UGtastic ▶ Speaking
And you have to define, when in the previous slide, you've been bound as a string?
Guest Guest ▶ Speaking
Yeah, so you're feeding it this events, this hash of events, and the convention here is that this is just the event that's gonna do the binding on, this is the function that it's gonna use. And this function needs to be defined within your view. So, if you wanted to call some other function that lived outside your view, you'd really just create a wrapper for that function and then call that function inside your view function.
Mike Hall Interviewer, UGtastic ▶ Speaking
So will the this be bound to the view?
Guest Guest ▶ Speaking
Uh, yeah, this inside the view is the view object. And there are a couple nice methods with underscore, I believe. I think it's the underscore portion of it that you can do like a bind all. And you can always give this being the view as the context of your functions in case you get lost in callbacks and nested functions.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, I'm sorry to...
Guest Guest ▶ Speaking
Sure, sure.
Mike Hall Interviewer, UGtastic ▶ Speaking
...but... No, no questions. I spend a lot of time trying to debug my crappy JavaScript.
Guest Guest ▶ Speaking
Oh. Very interesting.
Mike Hall Interviewer, UGtastic ▶ Speaking
Uh, but like, anytime you have something that's, you know, a string that actually has to match a function name, I'm gonna misspell it.
Guest Guest ▶ Speaking
Mm-hmm.
Mike Hall Interviewer, UGtastic ▶ Speaking
What happens if that function doesn't exist? Does it error out silently or loudly?
Guest Guest ▶ Speaking
You will get an error when you instantiate the view.
Mike Hall Interviewer, UGtastic ▶ Speaking
Okay.
Guest Guest ▶ Speaking
It will, you'll get an error that will appear in your JavaScript console in your browser. And, yeah, we'll get to the testing portion later, but it provides a nice loud failure when, if you're running tests, to see that you're binding the events properly. So that's really nice too, is that it's gonna make sure that you're binding the right thing. And it'll tell you if it's not.
Mike Hall Interviewer, UGtastic ▶ Speaking
Cool. I'm gonna go away again.
Guest Guest ▶ Speaking
Okay. Okay.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, um, if you have a view inside of another view, you know, I think it's powerful that you can, like, employ the views on top of views. Now, this isn't smart enough to just identify a new task inside of just this view. I mean, God forbid, the embedded view has a new task as well. Would it accidentally fire on this key up, if that makes any sense?
Guest Guest ▶ Speaking
The events that are bound inside of here are going to search inside of this view's element.
Mike Hall Interviewer, UGtastic ▶ Speaking
Okay.
Guest Guest ▶ Speaking
So if you have another view inside of it, it might accidentally. If you have a nested view that's also gonna render something with that ID, it'll pick that up.
Mike Hall Interviewer, UGtastic ▶ Speaking
Okay.
Guest Guest ▶ Speaking
Anything inside of there is fair game, essentially. Alright. So, that was the create on enter function. So here's the, for the tasks view. This is the view that we're gonna use to create all the different tasks, the individual task views themselves. So what we're gonna do here is use one of the underscore functions to say, for each model in the collection, we're gonna call add task. And then this return this here is a Backbone convention. When you call render, it's recommended that you return this being the view so you can chain calls. So you can return this element, you can do something else after it. Use that as you may, for chaining. Right now we have three misses. Yeah. So, and this is the add task function. So, here we actually do have a view inside of our task view. So the task view is responsible for rendering every model in the collection. But here we're delegating to a singular task view. That's going to render each of the models and the corresponding view along with it. So what I'm doing here is that inside of add task, I'm going to instantiate the task view. And I'm going to give it the model that I'm getting from iterating through the collection of tasks. So each time through, I'm going to instantiate another model and use it. This task L is just a convenience to kind of clarify what I'm doing here. So I'm doing a view dot render and I'm getting the L from it because I'm returning this in my function. L is going to be the element that the view is controlling. And then I'm going to take the task L. I'm going to search for the task class inside of my element view and then just prepend it to the list. So it's going to just kind of keep on adding things on the top as it goes. You can do an append. Actually this example is not the greatest because what I'm doing here is I'm really searching the entire DOM for a task class. What you can do is that you have a this dot dollar sign. So any queries that you might do with jQuery or whatever library you're using would be scoped to the view's element. So that actually could be a little bit better and search just inside of your view. And so your view's elements. Makes sense? Any questions? Okay.
Guest Guest ▶ Speaking
So, like I said, Backbone's about structure. We haven't really talked about anything like certain JavaScript template rendering libraries. We've talked a little bit about jQuery, but really we've got a way to just kind of take the part where you're dealing with the server and push it out to one side of your JavaScript code. You've got a section where the view is going to deal with the DOM and these things are kind of separated out. And as you start to separate those things out, you can see where you can start to hook in other functions that are your own, that you're namespacing on your own, other objects. Things that you can actually write the code for what you want your business to do and not necessarily have to worry about traversing the DOM inside the same statement. So, that being said, even with Backbone, you can make a mess. It's JavaScript and it's the DOM, right? And there's no guardrails. This is trying to help you make decisions about where to deal with certain parts of, you know, deal with the viewer over here, deal with the server over here, but I mean, like I showed you with that selector inside of, for the tasks, you can still just traverse the entire DOM and do whatever you want. There's nothing stopping you with Backbone. Backbone's not gonna get in your way, for the most part. So, so now what? Any questions on Backbone, the structure of Backbone, before we kind of move on into some scenarios? Okay, all right, so now it's time to make JavaScript dance a little bit. We want to actually tell them what to do and have it do it. So, there are really kind of two questions that I'm gonna attempt to at least show a path for tonight. One is how do you test drive client-side JavaScript, and then also kind of just relates to how you write clean JavaScript. How do you write JavaScript that you're proud of? So, before, four or five months ago, I don't know if I wrote any JavaScript that I was ever proud of. That I would show. To me, it was JavaScript that I would do at the last minute. I would find the jQuery function that would do it with the least amount of code possible, and then I'd say, "Hey, it's done." And then maybe I'd write a test that would fire up the browser and then execute the JavaScript and see if it renders something in the DOM properly. That was about it. And I wasn't very thrilled with it. And so, what I'd like to do is kind of walk through a couple scenarios of how a new web application could evolve its JavaScript and what steps you can take to move in what I think is a better direction than just everything in document ready.
Guest Guest ▶ Speaking
So, first scenario. So, like I said, let's talk about a web app with no JavaScript in it. Like any good web application, you're going to be collecting demographics information, right? So, they all do. So, let's say you want to add a feature where you want to show additional fields if you want to add additional emergency contact information. So, there's lots of things you can do, but let's consider two things. One would be, so in document ready, let's bind a function to a click event for add additional contacts, and then find hidden fields, fields that were hidden in the DOM when you load the page and then show them. Or, should we create an app namespace, initialize, and then bind an event to a show fields function? So, the show fields is going to take care of the showing of this given a certain event. Any thoughts on either approach? Well, that's okay, because you all probably would choose B, right? Which is great, because it's each namespace for JavaScript. Namespacing your JavaScript is probably the easiest thing you can do to make your code better. What you're going to avoid by namespacing your JavaScript is overwriting other JavaScript libraries. Any other JavaScript you include in your page. You know, I think jQuery, for example, maybe tries to protect itself from someone overwriting the dollar sign that you use. But if you're using other JavaScript libraries, there's no guarantee that they're going to protect the code that they use. And with JavaScript, you can just go in and redefine a global variable from doing this magnificent library of stuff into something that, you know, returns nil or undefined. So, namespacing it keeps your JavaScript separate, keeps it under control so you don't have to worry about people overwriting you with other libraries as well. And so, it's something I wanted to throw out there as something that's really important to do, really no matter what.
Guest Guest ▶ Speaking
So, we've namespaced it. So, in this next scenario, let's talk about testing it. So, with a Rails project, there's a Jasmine gem you can install. And there's a Jasmine library of JavaScript that lets you do testing. I don't know how many of you — there's a Ruby testing library called RSpec. And it's got this interesting, it's got a good syntax. You basically can describe it in kind of plain English of what it's going to do and these assertions on what it's going to do. And Jasmine does a good job of that on the JavaScript side. So, let's say that you've added a file called AppsBackJS. And so, right now, you have a jQuery selector that's going to find and show a class. So, it's going to go out and find the additional fields and then call the jQuery show method on it. And so, you start to think about what are your fixtures going to look like. So, when you're running JavaScript tests, you don't necessarily want to use the HTML. You don't want to have to fire up your entire web app to get the HTML that you're going to test. So, you can create fixtures. So, fixtures are just some HTML that you can use just for your test that you can execute your JavaScript on. So, there are a couple options. One would be to just copy the rendered HTML from your app into a fixture file and then load it in your spec. Or, you could set a fixture that looks something generic like this. You know, it's got a button with an ID of add. It's got some information there. It's got some hidden fields inside of a div. Some fields. Whatever your content is. So, any thoughts on which way may be a better approach?
Mike Hall Interviewer, UGtastic ▶ Speaking
Less code is better code.
Guest Guest ▶ Speaking
Me? Yeah. Good job, guys. Yeah. Exactly. Less code is better code. It's hard to find a compelling reason for loading your entire site's HTML file to test a certain portion of the JavaScript. What you end up doing is that you create this dependency on a snapshot of your DOM from a point in time that you're now responsible for maintaining if you expect your JavaScript code to work under those conditions. By writing a fixture that just has the bare minimum of code that you need to make sure it works, you're doing a couple things. One, you're going to speed up your test because they don't have to load an entire HTML file to run. And you're also kind of this exercise of figuring out what's the least amount of DOM I need to make this JavaScript work. You're not depending on a certain setup to make sure it works. You're going to say, okay, this is the stuff I need to make this JavaScript work. And you can make your JavaScript a lot more focused. Now, that kind of can get you into trouble if you are not considering any other possibilities of what can happen with it. I mean, you shouldn't have more than one DOM element with the ID of add, for example. It should be an ID. But now it's not really considering if there are ones with an ID of add that exist elsewhere. That ID is kind of a convenient way to get around that. But if it was a class, you know, maybe it finds other things that have that same class on there. So it would be aware of. But if you're writing the JavaScript and you're writing the HTML, that's something you can try and balance. But it's still something to be aware of.
Guest Guest ▶ Speaking
So moving on to the next scenario here, let's say you've got your fixture and you're ready to test. So how do we test this? Do you want to actually try and trigger the click event in our Jasmine test? That's going to make the fixture element visible? Or do we want to spy on this function that binds the event? Then call show fields directly and check the fixture afterwards.
Mike Hall Interviewer, UGtastic ▶ Speaking
Can you guys tell us in advance, next time, if there's going to be a test?
Guest Guest ▶ Speaking
Yeah. It's a pop quiz.
Mike Hall Interviewer, UGtastic ▶ Speaking
Yeah. Whoever said the answer is always B. I see a pattern.
Guest Guest ▶ Speaking
So with this add click, I mean, you're going to trigger the event. With the way Jasmine works, it's going to actually trigger events and you can do things like that with it. So this seems more like an integration test. You're testing a couple things at once here, right? You're testing that the element's bound properly and you're testing that the function gets called and you're testing that the function does what you expect it to do. It's a lot of stuff that's happening in not a lot of code. Which, I mean, that's kind of the real power of jQuery, right? That's one of the things that's so attractive is that you can do so much with so little jQuery code. Which is great, but it's not really great for separating out all the different things you can do in your JavaScript.
Mike Hall Interviewer, UGtastic ▶ Speaking
So is this the A answer? Is this stuff that you tried and went down that route and decided it sucked and then kept trying stuff until you found something that was better?
Guest Guest ▶ Speaking
Let's get through the rest of them. Actually, no, so these are things that I've done without testing JavaScript and it's things that I've tried to do while testing JavaScript. And as I've tried to do things that I would have done before, I found that I really am testing a lot of things. So this is part, it experienced me with JavaScript thinking, okay, well, I'll do this to test this as I figure out how to actually test JavaScript. And then also what really breaks it down into testing the nitty-gritty of these things that are happening.
Mike Hall Interviewer, UGtastic ▶ Speaking
In just that particular scenario, it looks like, I mean, that's the kind of thing that if I didn't know when I, you know, if I was new to it, I would probably try a, and then, like, three weeks later, someone would say, hey, why don't you do this? And I'm like, "Ah, yeah, duh," you know?
Guest Guest ▶ Speaking
Yeah, I mean, I had serious trouble testing JavaScript for the first month or so, probably. I would back up and try it three different ways before I felt comfortable with what needs to happen to do something. And 90% of my trouble was DOM-related. I was trying to do something with the DOM or a fixture, and I just needed to get the bare minimum out there for doing stuff with the view and then back out and start to write code that doesn't concern the view at all. And that was a big part for me, just trying to get over that hump. And so, we'll talk more about it, too, but that was kind of the prompt for some of these scenarios here. And the thing, too, is that with this B option here, I probably wouldn't have thought about it. So, you can spy on this binding function to say that it has been called with some Jasmine libraries. And then a separate test to actually call a show field and check that the fixture happens. That's something that lets you narrow down what's going to happen when you do a certain thing. You're just doing one action instead of several, then to one call. So, another scenario like that would be, well, why don't we have some client-side validation? So if you're trying to enter your social security number, if it's not nine digits, let's show something to the user right away so they don't have to wait for a save action and then a response from the server. So, this is kind of the same flavor. You could trigger a change event on the SSN field to say that something has changed and then that would cause the error to display or we can do kind of a similar pattern, spy on the bind function, call a function directly and then check the fixture afterwards. In this case, again, there's a lot happening. There's even more happening in this simple example than the previous one. And this is kind of why you don't want to just trigger events in your test. That makes your test harder to break down. So, with that option A, you're doing lots of things, right? Not only are you verifying the binding event and checking that your field is valid or invalid, you're going to check for the correct message of that validity check and you're going to be traversing the DOM to make sure that one, it got bound to the right element, and then two, that you've rendered the error message in the right spot. So, jQuery is really nice. It takes care of all this DOM traversal for you and a lot more, and it makes it so transparent to doing it that you kind of forget that you're doing this really complicated thing with a small call. And what I'd like to do is kind of let jQuery handle that, but then get far away from it as possible so I'm not reliant upon the results of that for the rest of my code. If I expect it to, I want to make sure that that happens properly, but then I can go and do something that doesn't really depend on the results of that in order to make my tests work.
Mike Hall Interviewer, UGtastic ▶ Speaking
And is this out of, because you don't want to rely on the browser, like you want to be able to test it in Node.js, or was it a speed factor? Like you found like 100 tests took like 10 minutes to run?
Guest Guest ▶ Speaking
So, it's a couple things. Speed is one thing. If I don't have a lot of DOM to traverse, it'll go faster. It's also for just separating out responsibilities of my code. It's easier to test what something should do if it's only doing one thing. And if you're expecting one line of code to do four or five things, that's a little bit harder to test. You kind of clumping all these responsibilities together into one thing, which again, I mean, I love jQuery. It's a fantastic library and I use it a lot, especially for DOM traversal. But it also is harder to test that you've got, you need to make all this setup and then do one thing and make sure that all your assumptions are met. It can get a little tricky. So, one pattern that I've done is that, instead of executing a function on the result of a jQuery selector, so it's going to go find something that I fire something based on what it gets back. What I'll do is that I'll do that jQuery selection, get that jQuery object, and then pass that to a function to deal with it. So, then my function can take that jQuery object and then do something with it. So, my test can just take a jQuery object in the setup and not have to worry about the actual finding of it. It separates the finding of the element with what you do with it when you get it. It's something that leads to easier testability and separation of your code. One of the patterns that I found really useful with the project that we've been working on.
Guest Guest ▶ Speaking
All right. So, that's the first four scenarios. And so, you've realized now that all this hypothetical JavaScript you were writing, it's kind of cluttered, right? There's lots of things that go on pretty quickly. So, you decided to attend this amazing session on Backbone.js in McHenry County, right? And so, then you think, wow, this Backbone stuff is pretty cool. So, you wanted to refactor your JavaScript to use Backbone.js. So, using Backbone.js, you can do all these things that you're going to do before, but you've got these objects to kind of separate them out. So, it's verifying the binding of the event by testing that your view's events hash is configured a certain way and making sure that that view is using a certain element. You're kind of taking care of that one portion of it. Now, you are relying on what Backbone is going to do for you with its events. There, I'm just deferring to the library. And that is something that I'm coupled to in my code. It's a choice that I made that I'm going to let this handle it, so I don't have to worry about cross-browser issues. This is going to handle it for me. This checking the logic of valid versus invalid, that's something that my model can do. I can check my model by calling model.validate. The message, you know, with all the checks that I have will execute, and it's going to return a message for me. So, given a certain state of the model's attributes, I can expect my validate method to return an error message for me. And then, finally, in my view, if I get an error back from the model, I can check that when I give it this model with this error message already, that it's going to add it to the right spot. So, I don't have to trigger the error message in order to see that it's been inserted in the right spot. I just have a function that says render error messages. And it's going to go, you give it the error message when you call the function, and that function is going to take care of rendering it. It's not going to have to do all the work it wants to validate it.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, instead of having one long test that goes through all four steps, sequentially, you would have basically four different tests that aren't dependent on each other.
Guest Guest ▶ Speaking
Yeah.
Mike Hall Interviewer, UGtastic ▶ Speaking
That are, because then, if it's failing at step three, you know it's just that.
Guest Guest ▶ Speaking
Yeah, and it helps you kind of see where your code is reusable, too. This validation pattern is really common. You're probably going to want to use it for any client-side validation. So, you start to see where you can reuse these functions instead of just kind of doing everything at once all in a row. And those integration-style tests, they certainly have value as well, but you don't necessarily want to use those by themselves. These unit-style tests give you, they help you expose where your codes are usable if you're separating out these responsibilities.
Guest Guest ▶ Speaking
So, let's talk about refactoring with Backbone in mind. So, you want to use Backbone to show hidden fields in your HTML. So, actually, the answer to this one may not be B. This one is kind of B. So, a Backbone view event-binding and a function that unhides the view's L, let's just say it calls the jQuery show method. Or, that you have an event binding and a function that's going to render a JavaScript template. That's what JST is here. It's just a shorthand for a JavaScript templating convention, the Jammit package. It's one of the things that Document Cloud and Jeremy Ashkenas published as part of their open source projects. Anyway, it doesn't matter, it's just a JavaScript template. So, rather than, say, manipulating the existing DOM to unhide something, would you rather have it just event-bind and then render something brand new on the page? So, the content doesn't exist at the time the page loads, it's going to exist when you add it, when that event occurs. So, now you've got a case where you can either rely on the DOM to have what you need before you start up all your JavaScript on document-ready or you can have your JavaScript insert that content for you. Any thoughts on what may be a better approach or the pros and cons of each, I should say?
Mike Hall Interviewer, UGtastic ▶ Speaking
I think it has a potential to be a little slower.
Guest Guest ▶ Speaking
Potentially, yeah. So, what's interesting, actually, is that client-side rendering depending on your browser and your machine can actually be pretty quick. In some cases quicker than the rendering that's going to happen server-side that gets sent back up with a response. But you're right. If you're rendering a lot of stuff, that can be kind of slow. And if you've loaded it all beforehand and now you're just unhiding it, it's going to be there, you're just now toggling the style on it. And what I found, too, when I have these, you know, I'm working on a project with a front-end designer, and they're used to working inside of HTML or Haml or whatever it is that they're used to manipulating, and now they have this separate templating they need to learn, that can be tricky, too. It's hard to move back and forth as a designer that's working on this if someone else is just creating all different kinds of templates. So it's another set of templating that you've got to learn to use and then use properly. As far as a guide for this goes, I don't really know if I have one. What I would say is if it's hiding and unhiding additional fields, maybe that's something I would just load in the DOM and unhide versus trying to render that content separately. Because that's going to be pretty static. I'm only going to have one instance of these fields. But say in a to-do app, if I'm going to have a lot of tasks, I don't really want to have just one hidden version of the edit form that I want to use for everything. I can just add and remove that from the DOM as I go and then a JavaScript template is really nice for that. Some things that I've done, I've tried a couple different patterns. You know, if I feel like I've got this static display of content, like a table that's got a certain amount of elements that I want to fill out, that's pretty good as static HTML. And then I just give that to a Backbone view to watch and render things inside of or manipulate inside of. But if I've got content that's going to be pretty dynamic, and I don't want to wait for the server to respond with what I need, using JSTs has been a pretty nice thing to have. Because it does happen pretty quickly, at least in modern browsers.
Guest Guest ▶ Speaking
I kind of alluded to this before, but so with jQuery, it's really nice. This is from the creator of jQuery. It's pretty accurate. There's problems all over. And I like jQuery because it handles a lot of that cross-browser compatibility for me. I read that jQuery is, I think John had said, and I think I read it's on the jQuery site, but essentially if a browser has more than 1% usage in the standard metrics, jQuery is going to support it. So you can be pretty sure that jQuery methods are going to do what you expect them to do, regardless of what browser the user is using. So that's really nice to not have to worry about rewriting every single thing that needs to happen across IE, across Firefox, Chrome, Safari, whatever. But that being said, just know why you're using jQuery. If you're using it for DOM traversal, I think that's a really good way to use it. You know, there's all sorts of plugins too. There are validates plugins. There are things that, you know, maybe you'd want a model to take care of versus some plugin to handle. There are lots of really nice UI plugins as well. It's just something that you need to be aware of. And if you're trying to separate out your responsibilities in JavaScript code, it's really easy to clump them all together and just rely on a library to do that stuff for you. I think your mileage is going to vary. You know, just going out and looking for plugins is a good way to get something that works reasonably well pretty quickly. But unless you're going through and looking at the source code of the plugin, you may not really know what it's doing. And you may get yourself into using and relying on some library that isn't really all that configurable, is relying on certain assumptions that may just not be supported as well. jQuery core, I would rely upon pretty much, not without question, but I wouldn't really hesitate to plug that in if it's something staring in jQuery. The same thing could be said about any Ruby gems or other plugins to other frameworks. I mean, there are some gems out there that you can write in the morning, you know. And they're not supported a month later either. I mean, oftentimes, I feel more comfortable writing the code, even if it means a little more work. If I write it and I've got a test for it and I know exactly what it does, I feel better about that code. And it's going to keep on doing what I want to, and it's going to be easier to modify later when my requirements change. So that's the general point. Now, you can still test what those libraries are doing to some degree. If you're going to call within a Backbone view or something like that, you can spy on that call. You could stub it out just to make sure that it gets called. That, again, is kind of like the namespace thing. It's sort of a general thing that I've learned about trying to test JavaScript that's been helpful to me.
Mike Hall Interviewer, UGtastic ▶ Speaking
So when I'm evaluating a gem and deciding if I want to use it, I'll go and I'll look at the tests. And actually see if they wrote any tests at all. Right? And, cause a lot of times — is there something similar you can do when you're looking at libraries? Like?
Guest Guest ▶ Speaking
Well, don't look for tests cause you probably won't find them.
Mike Hall Interviewer, UGtastic ▶ Speaking
Right. I mean, probably anybody writes tests for those kind of libraries. But, you know, is there some other, like, smell that you would look for when you're looking at a JavaScript library?
Guest Guest ▶ Speaking
Um, you know, the validates. I mean, that one feels a little funny to me. That you've got this thing that's gonna, you're gonna bind some events to a certain field. And then you've got validations that are gonna happen. I mean, it seems like that should be something more that a model in Backbone should know about. Rather than have some general plugin that doesn't really relate to any, you're gonna have to have a valid — that's one example.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, if it's doing something that really that one ought to be doing, you would say don't track, you know, avoid the plugin.
Guest Guest ▶ Speaking
I wouldn't say avoid it. I would just say, be cognizant. I mean, maybe another one is the Ajax form plugin. So, you've basically got this, and this kind of gets to the Ajax form plugin is something that essentially, you can use it on a form that exists as just static HTML. And it is going to intercept the submit, the submit button that you click. It's gonna intercept that, submit your form as an Ajax call. So, you can do all this stuff here. If JavaScript is working, then it can do it Ajax, and it's not gonna refresh the page or flicker the page when you submit it. You can do something else afterwards. But if JavaScript is disabled, then the form works as expected with HTML. So, that's cool. I mean, that's not intrusive, right? If it doesn't work, then it doesn't work, and the HTML one works fine. But that kind of full interception of what it's doing and submitting, it's really convenient. But the moment you want something slightly different, then you're kind of stuck with this plugin. And that's maybe a better example of kind of going down this route of some convention, some plugin. And really what you want is finer-grained control. Depends on how much control you want, I guess. Or how much you expect to need.
Mike Hall Interviewer, UGtastic ▶ Speaking
Well, that particular scenario kind of screws up your separation of concerns. Whatever you've got figured out, it imposes its own approach.
Guest Guest ▶ Speaking
Yeah.
Mike Hall Interviewer, UGtastic ▶ Speaking
You might not like it.
Guest Guest ▶ Speaking
I mean, it's something I've used before, and it's really nice, because you write 12 characters of JavaScript, and you're done. You get the Ajax call, and everything's good. So, there are certainly advantages. It just depends on, when you get into really client-rich applications on the website, finer-grained control is usually what you end up doing.
Mike Hall Interviewer, UGtastic ▶ Speaking
So, if you were walking into a new project today, how sure would you be that you'd use Backbone.js, or would you want to see what other frameworks are available? You know, I've heard a lot about Ember.js lately.
Guest Guest ▶ Speaking
Ember, it seems like the equivalent, like Ember is kind of, just all this past judgment. It's kind of like the Rails of JavaScript frameworks. There's a lot of convention over configuration there. You've got the ability to kind of take things out if you don't want them, but it's very opinionated in saying that we're going to use this templating library. We're going to expect you to render things in this fashion. And I do end up writing a fair, you know, when you're starting with a new project with that one, you may end up writing a lot of the code, the same, you know, over and over again. And that can kind of just mean that it's time to abstract something out. And I like to have, maybe it's just my hesitation with my knowledge of, my deep knowledge of JavaScript, but it's nice to have that fine-grained control over it so I know that it's doing what I want it to do. So, at this point, I don't think I would — I would write JavaScript without Backbone, but that's because I've kind of seen what you can do with Backbone.js. You've got this — that's the really nice thing about it, just to kind of segue into my next slide here, it's just a framework, right? The nice thing about Backbone is that it doesn't really get in your way. It doesn't demand you use certain libraries or certain templating plug-ins. It shows you how to separate out these responsibilities, and if you want something that communicates with the server a certain way that Backbone doesn't do, it kind of provides a template for how that code would look. Same thing with rendering to the DOM or controlling events. It's this really nice way to — it provides a structure, something that you could use. And I've used Backbone just to control events on an element before. No rendering at all. I just like having it define its events, and I feel pretty comfortable with it. I really love talking about it.
Mike Hall Interviewer, UGtastic ▶ Speaking
What are your thoughts on CoffeeScript?
Guest Guest ▶ Speaking
CoffeeScript? Um, so my thoughts on CoffeeScript are, if I was starting over and I didn't know anything about JavaScript, CoffeeScript would be really nice. Having gone through the pitfalls of JavaScript for a while now, I can write JavaScript that avoids the things that CoffeeScript tries to help you avoid. Like namespacing properly, like doing comparators that make sense, you know, it doesn't try and coerce your types from a string to an integer for you if you do a double equal instead of a triple equal. There's that book JavaScript: The Good Parts by Douglas Crockford. The best part about that book is the appendix where it's like JavaScript the awful parts. Because that's the stuff that CoffeeScript basically says, this is really dumb. We're going to write this in a way that it avoids this stuff for you. It's weird jumping to it from JavaScript because I feel like I'm missing something and I just kind of start typing it. But, you know, it's also, even though it compiles down, it's also kind of lower ceremony as well. Like you don't have to type all the blocks. It's going to create that closure for you. It's kind of like someone just read JavaScript: The Good Parts and said, okay, this makes more sense in language. So it's a convenience and it compiles down to JavaScript, so. All right. That being said, I haven't written much of it. Any other questions? I think I made my point. I'm not sure. Anyway, I mean, it's good. It provides that structure. That's the basic takeaway with Backbone. Other kind of summary things that kind of help me lead towards clean JavaScript is namespacing. 100%. I would never not do it. If you're writing tests, minimize your fixtures. It makes your tests fast. And it helps you write more focused JavaScript.
Guest Guest ▶ Speaking
You mentioned runtime for tests. I've got a six-month-old MacBook Pro here. On our project, we have, I think, 700 Jasmine tests right now, and they run in Chrome in about a second. So it can be pretty speedy. I think, you know, Safari, it runs in three seconds or something. But they're really quick. And that's because we're not loading any fixtures. There's a project that I'm working on that had 800 line fixture files. And 50 of them took 10 seconds to run. So it can really bog you down.
Mike Hall Interviewer, UGtastic ▶ Speaking
So is it to say that the 700 tests that you run in the second, you're not doing any DOM manipulation or you're just minimizing stuff?
Guest Guest ▶ Speaking
I'm manipulating the fixture that I'm working on. And it's really that I'm saying, okay, the fixture just has a single div with this one class. When I execute the test, I expect it to insert some validation error inside that div. I don't have to traverse the entire DOM to find out how to load the fixture, you know, before I run each test to make it happen.
Mike Hall Interviewer, UGtastic ▶ Speaking
So you're manipulating the DOM, it's just—
Guest Guest ▶ Speaking
Yeah, it's just in very small, isolated places. And you just — I mean, you can't get away from it. But you can certainly make it as small as possible.
Mike Hall Interviewer, UGtastic ▶ Speaking
Yeah, because that was kind of the question I had was if you're trying to get away from relying so much on jQuery, are you spending a lot of time mocking what jQuery does for you?
Guest Guest ▶ Speaking
Not a lot of time. I mean, there's certainly parts of it where the part where you're interacting with it, you've got to deal with it. But the same thing goes if you're trying to deal with a database. You've got some tests that are going to deal with your database section. But once you've got that figured out, then you can mock out everything else and test your business logic that just, you know, can do its own thing. That kind of leads me into another point, which is really just making sure that you're separating responsibilities and actually unit testing your code. Again, integration tests are fine, and they're good, and they catch things. But unit testing provides a deeper layer of coverage that I think is really valuable. Any other questions?
Mike Hall Interviewer, UGtastic ▶ Speaking
Can you show us a test?
Guest Guest ▶ Speaking
Yes, I can. So, there are some links to my GitHub repos. Let me pull up my Rails version that was on the thumb drive. That was super quick. So, right now I've got nothing on the screen. So, I've started up Jasmine as just running locally, and let me point my browser to this. So, this is the suite of tests I have for JavaScript for the Rails version of my to-do app. Since they depended on Jasmine, I didn't translate these for the local storage version. But you can take a look at them when we get in the repo. Let me expand these so you can kind of see what the tests look like. So, for the collection and models, I've got some pretty basic setup type tests that it's using the task model. The URL is defined as what I want it to be. We've got some validations about what an empty description is and if that's invalid or what. For the views, some event bindings, what these actual functions are doing. Let me pop open the code and show you what some of these look like. So here I've got a before each block where I'm doing some setup for each of the tests. I'm essentially, this JST here, this is the template that I want to render inside my view. And I have made the decision that I don't care what my view renders. This app is simple enough that as long as it's rendering, that's fine by me. This is just some empty function that I can spy on or stub out that to make sure it gets called. I've got a test model here. I'm stubbing out the save method because I don't want to try and trigger a save to the server when I run my specs. And then I've got a view that I'm going to use in my test as well. I'm going to give it the model and then I'm going to restore it so I don't have any problems with my setup between tests. So let's render the template test here. What I'm essentially doing is I'm setting up a spy with Sinon.js. This is a stubbing mocking library that's available for JavaScript that I've really enjoyed using. The Jasmine spies, if you're using Rails, are nice as well. This is something that I've just gotten in the habit of. So what I do is I'm just going to call render on the view. And after I call it, I'm expecting that that template spy was called and that I was passing the attributes of the model along with it. So to show you the actual code it's running against, this is the edit task view. This is what the render function is doing. It's getting the HTML from calling this template as a function with the attributes. And then it's going to append it to the L through the HTML, the jQuery HTML function. And then it's going to return this. So that's essentially what that test is doing. Let me show you — any questions on the viewed one. Jump back up again, too.
Mike Hall Interviewer, UGtastic ▶ Speaking
What did you say the testing point was called?
Guest Guest ▶ Speaking
Jasmine is the plugin. A little bit, yeah. So... Let me open up the task. Okay. So here for the validations, I'm creating a task with no attributes on it. When I call validate, I want to check that the description, if the description's null, that I want that to be invalid, so I'm expecting that the first error in the errors attribute here is going to be equal to this field of description and this message, and then vice versa, I call it and I've got some description in there that there are no errors, and then this validate function here is essentially doing just that. And then basically it's constructing an array that I give it a list of objects with all those fields and error messages there. Any other questions or things you'd like to take a look at?
Mike Hall Interviewer, UGtastic ▶ Speaking
Have you had experience running the Jasmine tests in a continuous integration server?
Guest Guest ▶ Speaking
Yeah, so we, at my client's project, we use Hudson, and it runs on a Linux server. And so there's some setup you can use to run it basically on Firefox on the Linux server. There's a couple of commands you can use, and you can run Jasmine as like a CI task for a Rails application. Not to get too Rails-y, but so a task you would get would be the Jasmine CI. What that's going to do is it's going to fire up a Firefox browser on this screen, you'll just have to believe me. And then it outputs the results of it to the terminal here.
Mike Hall Interviewer, UGtastic ▶ Speaking
And that comes with the Jasmine?
Guest Guest ▶ Speaking
The Jasmine gem.
Mike Hall Interviewer, UGtastic ▶ Speaking
Okay. Yeah. Cool.
Guest Guest ▶ Speaking
So, yeah, that's a good question. And so for the dependencies, I'm kind of managing it by hand. I'm just including them in the right order when I'm setting up my JavaScript includes. I think on our project we're using the Rails has, there's like a JS manifest you can use where you can list out all the files, and it's going to compile them to one single JS file that it serves. There's, I think there's a handful of libraries, but that's the one we're using on our Rails application. Some type of a compressor. I'm not sure, it doesn't minify it in development or QA mode, but then in production it can also minify it. So it really just takes out all your extra spaces. So, actually, that kind of reminds me, one thing that we do have is a gem that will run JSLint on our JavaScript, on our application files. And so you can configure that — JSLint is basically the syntax checker that Douglas Crockford, the JavaScript: The Good Parts guy, wrote, that will tell you if your JavaScript has just the good parts or the bad parts. That includes semicolon placement, JavaScript will insert semicolons for you if you didn't do it, and it will guess where that may be. So, if you're trying to compress all your JavaScript into no spaces in your production file, and you're missing semicolons, then bad things can happen. So we actually have that running as a task on our Hudson server as well. If there are any JSLint failures, then our build fails, you know. Which has been helpful. And makes sure that we're not going to run into any of those weird JavaScript-y types of errors later when we're actually using it in production.
Mike Hall Interviewer, UGtastic ▶ Speaking
Have you had any experience with, like, modules?
Guest Guest ▶ Speaking
Uh, not a lot, I mean, I think the nice thing about the Rails projects I'm working with is that it kind of has some of that stuff built in for me. I've heard a lot about it, and it does sound pretty slick, but just nothing I've got a lot of personal experience with. Any other questions? Let me toss this GitHub link back up on here. All right. Well, thank you, everybody.
Mike Hall Interviewer, UGtastic ▶ Speaking
Thank you very much. Thank you.
Guest Guest ▶ Speaking
It's my birthday, you know, if you. Thank you.