The source code for this post is available on gitub.
While Backbone does give your project structure, it does not give you the full feature set that you require to build a web application. Many methods are deliberately stubbed out and you are encouraged to fill in the blanks to give you the desired functionality. One such method is the validate method on a Backbone Model.
The validate method is called every time
save is called on a model. The aim here is to override the validate method to use an object defined on the model and use this for validation. We will also add an errors hash to the model which can be displayed to the user.
Validations are perfect for unit testing, you have an input and a desired output and not much in between. I will be using Jasmine for this purpose. The first step is to download the spec runner. You can then extract it and locate the SpecRunner.
After downloading, delete the two files
SpecHelper.js and create a new file
validator_spec.js. Then go into the src folder and delete
Song.js, you should also create a file
We will also need Backbone.js (0.9.0) and Underscore.js, put these files inside the
Finally, the file
SpecRunner.html needs to be modified to reference the files you created. It should look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
If you have read any Backbone tutorials, most will recommend that you namespace your application. For this application, I am going to use
Gazler as the namespace, you can pick whatever you like.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
A few things of not here:
- We have bootstapped a model here, this is all we will have to touch on Gazler.Model
- Validate only returns if there are errors, Backbone will not continue with the save action if validate returns anything
- We have added an empty validates hash, this will be where we store our rules.
- We have added some strings at the top, normally these would be generated from the language file you are using (config/locales in ruby)
With everything ready to go, we can write our first test.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
This should be pretty self explanatory, the key part here is that we add the validates hash to the model before each test and then call validate. We then simply check the errors hash against what we expect it to output. If you open
SpecHelper.html then you should see that this test is failing.
To make this test pass, we need to run through the rules specified in the validates hash and see if any of them have been broken. In order to do this, we need to add some code to the Backbone.Validate method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
That code block can be quite a lot to take in, but I’ll try to explain it. The first thing to not is that it returns the results of a self-invoked function. The reason for this is to keep the scope of this throughout the Validate method.
Inside this function, we maintain our own references to errors and attributes. This is because we don’t want to do anything that could affect the values that are on the model, which is not the goal, we want to let Backbone deal with that. We use the clone method of underscore to keep our own reference.
Using the extend method of Underscore, the changedAttributes are merged into our attributes reference, this means that
this.attributes contains all the attributes present before validate was called, and the new ones too.
The code on line 7 is used to call a methods defined in the
this.validators hash. Currently there is only one method defined there, but we will expand that in the future and add more validators, such as numericality or format.
As required is the easiest method, that is the first one to implement, Simply using the
_.isEmpty() method, you can determine if a required field is present or not. if it is not present, there is a small helper method to push the error onto the errors object.
If you re-run the test(s) now then you will see that our single test is passing.
There are two more tests that we should add before we are done with the required method. Both should go inside the describe(“required”) block.
1 2 3 4 5 6 7 8 9 10 11 12
These two tests should be fairly obvious in they’re purpose. One thing of not is in the test with no required fields, we are testing that the validate method returns undefined. As mentioned earlier, this is because Backbone required you to not return anything if you want to continue with the set/save after validating.
That is it for part 1. We will take this concept further in part 2.