3: Installing ng-boilerplate, and serving it through rails

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:

Tutorial_2 vanilla ng-boilerplate

There are three key decisions here:

  1. 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.
  2. A choice to use the ng-boilerplate template rather than the more standard Yeoman templates for the AngularJS directory structure and tools
  3. 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

Rather than:

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 install

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 grunt build, where it copies your javascript files into the 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 bin directory.

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.

We’ll edit build.config.js, changing the following line:

  compile_dir: 'angular_bin',

We can then run grunt without worrying about losing our rails directory.

grunt build

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):

file:///home/apps/league-tutorial-rails4/build/index.html#/home

Finally, we want to have this app served through our rails server, rather than opening from the file system. To do that we’re going to link our angular app into the public directory of the rails server, which will let the angular content be served directly. This makes sense because the angular app is similar in concept to the assets that get served from the public directory – it is mostly javascripts and templates, and the content should be largely static – i.e. the same for every user. We’re going to link the build directory to appear in public/UI

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.

Advertisements

6 thoughts on “3: Installing ng-boilerplate, and serving it through rails

  1. Pingback: AngularJS and Rails 4 CRUD application using ng-boilerplate and twitter bootstrap 3: Tutorial Index | technpol

  2. Pingback: Creating the base rails backend | technpol

  3. Not clear on the question there Loi Tran. The javascript should all be compiled by the ngbp setup, via grunt build and grunt compile. The css should all be symlinked to be less, and then gets included through the less compilation process. If you really wanted css you can just add it as an asset I think and it will get included through the asset copy process.

  4. Where have you read this: “ng-boilerplate is close to version 4.0, and that version will change the structure substantially”? From what I can see ngbp is now only at v0.3.2, so it seems a bit strange.

  5. The new version is called warlock, and there is a bit of commentary about it through the ngbp issue tracker.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s