Thursday, August 15, 2013

Stop Complaining about the Angular.js Docs

This article assumes you've used github but that you're not a pro at contributing to large projects.
After rolling out some internal angular.js apps for my team I found a lot of people can be confused by the angular docs. Its documentation covers many things, but the examples and explanations don't always make sense to those new to angular. Just the same as with any open-source project, the poor documentation is just as much my responsibility as it is the responsibility of anyone on the Angular team.
How much documentation had I written? How many pull requests had I sent? The answer, obviously was none, so I went to github, forked the project and decided to make the ng:class docs suck a little bit less.
I was pretty sure at this point that it would take me about 5 minutes to come up with a better example, but it ended up taking me many nights to get it just right and finally get some small changes merged back into the main project.
I don't want you thinking it's too hard or a waste of time. It is totally worth it! I'll share what mistakes I made and what I found complicated, so you can help improve the docs right away!

Getting Setup

Before starting you'll need to have reasonably new versions of the following software installed on your machine:
Then you'll need to fork the project and check it locally. You may also want to create a branch where you can do your work.
git clone https://github.com/YOURNAME/angular.js.git`
cd angular.js
git checkout -b docs_update
Now typing the grunt package command will prepare your files for being viewing and testing locally.
grunt package
With that in place you should now be able to browse the current docs by going tohttp://localhost:8000/build/docs/.

Where is the documentation?

All of the documentation, including examples, is found within the angular.js source code. For example, the ng:class source code is located inside of the src/ng/directive/ngClass.js file. The code examples use custom markup (angular directives) that look something like this:

<example>
  <file name="index.html">…</file>
  <file name="style.css">…</file>
  <file name="scenario.js">…</file>
</example>

  
These correspond with the tabs generated in the example portion of the documentation.

Making Changes

When you are ready to start editing the documentation examples you can just press the "Edit" button included on each page. This button will take you to a working version of that example on a 3rd party site that you can modify to your liking.
Once you've modified the code enough paste it back into the comments of your source code, comment it out and make sure it works.
After you make a change you should
grunt docs:process
Once that's done you can check your work locally by running a webserver and viewing the documentation.
grunt webserver
This will start a local webserver on port 8080 and allow you to visit the docs at a URL similar to this one:http://localhost:8000/build/docs/api/ng.directive:ngClass
Some of the CSS used in the angular docs may be different from what is used on the site where you edited your example, so make sure you check out your example on the actual documentation site.

Testing your work

Angular has this amazing things where the tests are run from within the documentation. This is done inside of the <file name="scenario.js"></file> area in the <example></example>. More than likely the example you're updating already has some basic test, but you'll want to update it with your current code, process the docs, and the run them:
grunt docs:process
grunt test:e2e
Try to make your tests as comprehensive as possible.

Submitting your work

Once you have made sure your tests pass and you've got what you think is a better example than before you can submit your pull request to the team. Point your pull request at angular.js/master.
You will probably receive a lot of feedback about your pull request. My small changes to ng-class took about a month of back and forth before being merged which you can read yourself.
But I was super happy when they finally went live recently. Hurary

Helpful Tips

Solving Problems

What happens if my branch gets really out of date with the main angular branch?
In these cases you should rebase with the main angular repo and resolve any conlicts. The first step to doing that is setting up a new remote origin called upstream that will let you hook directly into the angular repo.
git remote add upstream https://github.com/angular/angular.js.git
The second step will be to rebase your branch against that repo:
git rebase upstream/master
For more information about rebasing please check out github's suggested regarding this matter.
What about filling out the CLA?
A community licensicing agreement is basically a way for Google's lawyers to be sure that you're not going to claim you have any rights to the code after you give it to them. You can't sue them for abusing your pull request. It's unclear for contributing docs if it's required, but the instructions can be found here:http://docs.angularjs.org/misc/contribute

Saturday, January 19, 2013

Versioned APIs with Express

After reading and watching some of the stuff coming out from Apigee about API Design, I've been convinced that APIs should probably be versioned in the URL using a scheme like this:
http://api.whatever.com/v1/jobs

By the time I realized this the API I had been building with node.js was basically already complete, so I was a little bit sad that I'd have to come up with some complicated versioning scheme.

After a bit of fretting I realized that express can handle this super easy using an interesting feature of the express() instance that it can be mounted to another route using app.use().

This means that your routes don't know which version they are!

Here's your main app file.

app.js file

Then you'll put each version of your API in the routes/ folder named after the version.

routes/v0.js file
Each version of the API can have middleware (such as unique authentication) that only works on that version of the API. One thing that this doesn't cover is unique models per version, but I'll leave that up to you to figure out how to accomplish, because the needs of each app very quite a bit by app. Hope this tip helps!