In section three of the Rails 4 and AngularJS tutorial, we make use of the excellent ng-boilerplate template provided by joshdmiller.
Note before you begin this section of the tutorial that ng-boilerplate is close to version 4.0, and that version will change the structure substantially. I’m planning to plug that content in over the next few weeks as it comes available, so expect this tutorial to be evolving. It should be fit for use, but if you complete it over multiple days you may find that it changes under you whilst you’re doing it. Caveat emptor.
At the end of this section we should have a page that is basically the ng-boilerplate demo page, but served up using our rails app:
There are three key decisions here:
- A choice to use the native AngularJS packages and tools, rather than using the AngularJS Gem for rails, which I think is the approach taken by the always excellent RailsCasts.
- A choice to use the ng-boilerplate template rather than the more standard Yeoman templates for the AngularJS directory structure and tools
- A choice to co-locate the Rails and AngularJS code in a single directory.
I’ll discuss each of these in turn, with my rationale. I’m pretty sure much of what follows in the tutorial would work with different decisions, but I don’t guarantee that. I’d recommend completing this tutorial using those decisions, and then try it again once you understand it all, using a different framework or approach.
Starting with the choice to use native AngularJS functionality. Basically I’m choosing to build a JSON-only Rails server, and then run a loosely coupled AngularJS client. This should let me use any of the AngularJS templates and tools that I wish, and not be limited by how fast or slowly someone updates a Rails gem. It should also allow me to replace my backend at a later date (or frontend, for that matter) without having issues.
It does have some downsides though. There are some functions and features that Rails provides that would be nice to supplement the AngularJS functionality, to pick an example, the ability to determine the preferred language of the user.
At the end, my conclusion was that I’d use the Gem if I wanted to take an existing Rails app and supplement or enrichen it with AngularJS. But if I wanted a full AngularJS client then I felt I was better making that standalone.
Next, the decision to use ng-boilerplate rather than Yeoman. I like the format of the ng-boilerplate template, it groups the files by functional area, rather than by architectural layer as the standard Yeoman templates for Angular do, and as Rails does.
This means you get:
clubs/ clubs.js clubs.spec.js club.tpl.html clubs.tpl.html teams/ teams.js teams.spec.js team.tpl.html teams.tpl.html
controllers/ clubs.js teams.js tests/ clubs.spec.js teams.spec.js partials/ club.tpl.html clubs.tpl.html team.tpl.html teams.tpl.html
As your project gets larger, it’s much nicer/easier when all these files are side-by-side, and it makes it easier when you decide to write some common components that you want to move into another project – you can just pick up and move the entire directory, and most of what you need is there.
Some people have asked about Yeoman, and I confess I have done only some research on it. It looks to be a great tool, it provides scaffolding in a similar way to the rails generator (i.e. it creates your boilerplate/framework for you). Having said that, it creates it in the standard AngularJS directory structure, and that is less useful for me than the ng-boilerplate structure. And later in this tutorial I’ll show how to have the rails generator create the AngularJS boilerplate for you, which should mean you wouldn’t need Yeoman.
Finally, the decision to put the AngularJS (and boilerplate) files in the same directory as the Rails files. I’ve done this mostly because it makes management of my git repository easier, although with hindsight an equally valid approach would be to create the following folder structure:
league-tutorial-rails4/ rails angularjs
And run git at the parent directory level. The main downside of the way I’ve chosen to do things is that both ng-boilerplate and Rails 4 want to have a bin directory, and ng-boilerplate clobbers the bin directory whenever you do a build. I’ve noted later on how to avoid that. The downside of going the other way is I think it would make using the rails generators to generate AngularJS code harder, although I’m sure there are ways around that through sym-linking or other techniques.
OK, so lets get on with getting AngularJS and ng-boilerplate. Start off by installing node.js on your machine if you haven’t already got it (if you already did the Rails 3 version of this tutorial, you already have it). If you’re on OSX (as I now am) your best bet is to download a prebuilt package. If you’re on linux you can find some instructions on joyent’s github, or look at the instructions I provided on the rails 3 version of this tutorial. I’m strongly recommending you get a MacBook though!!
Once you have node.js installed, you’ll want to clone the ng-boilerplate repository. We’re not keeping ng-boilerplate as an upstream of our repository, as we’ll be changing things that we don’t want to have to merge later. If there are later changes in ng-boilerplate that you want, you’ll therefore need to merge manually. Again, you could make a different choice in your real app, remember this is only a tutorial!!
git remote add ngboilerplate git://github.com/joshdmiller/ng-boilerplate.git git fetch ngboilerplate git merge --squash ngboilerplate/v0.3.1-release git commit -m "Merged boilerplate"
You’ll potentially get conflicts at the merge stage on the .gitignore file – if so edit that file to keep the superset of all changes, then execute the git commit -m. Next, we install the build and test tools
sudo npm -g install grunt-cli karma bower npm install
Npm is the node package manager, so this is telling the node package manager to install stuff for us, namely
- grunt, which is the scripting tool (sort of like make in C++, or rake in ruby/rails).
- karma, which is the test toolset, similar in concept to rspec in rails
- bower, which is an installation tool, similar in concept to bundle in rails, with perhaps bits of the Gemfile thrown in
Bower is another installation tool, I haven’t yet worked out why we have both npm and bower, other than that I think that they are somehow complementary. Which isn’t a great answer. My feel is that npm is for installing node-specific things, bower is more for generic AngularJS stuff.
We’re about to run grunt, which will build our AngularJS app for us. Grunt runs in two modes, it can either run in “development/test” mode using
build directory without minifying them. This makes debugging in your browser much easier. Or it can run in “production” mode using
grunt compile, where it will minify everything and put it into the
The main issue here is that we already have a bin directory for Rails 4, and every time we run grunt it’s going to clobber it. So, before we run grunt for the first time, we’re going to adjust
build.config.js to tell it that we want to have
angularjs_bin, rather than
bin, for our compiled directory.
build.config.js, changing the following line:
We can then run grunt without worrying about losing our rails directory.
This should build a base application for you. If, like me, you are don’t have Firefox installed, this will give you an error that it cannot find Firefox, which prevents the unit tests from running. You can sort this by editing the browser setup at the bottom of
karma/karma-unit.tpl.js to use Chrome instead. Alternatively, you can simply to leave the browser out (as I’ve done).
browsers: [ ]
If you leave the browser out, when you run grunt it will wait for a browser to connect. You can go to a tab in your browser and visit http://localhost:9018, and your browser will connect to karma (within grunt), and allow the unit testing to run. If you do this and use Chrome, then I recommend opening a new window with only 1 tab, and connect that to Karma. Tabs that aren’t in focus appear to get lower priority, your testing will run much faster in a foreground tab.
Try opening the application directly from the file system by entering something like the following into your browser (you’ll need to edit the path to match your working directory):
cd public ln -s ../build UI
Note that symlinks don’t get checked into git, so you’ll need to recreate this on any new checkout. We should now be able to get to our app from http://localhost:3000/UI/index.html:
The code at the ending point of this tutorial 3 can be found on github in the tutorial_3 branch.
In the next segment of this tutorial we’re going to tie the two together – we’ll change our angular app to get data from the server for the club entity.