While it is possible to include AngularJS as part of the rails assets, I think it is better to setup the angular code base on a standalone folder, leaving the rails app as a (more or less) isolated backend.
There are several advantages to this setup:
I want to stress out the convinience of working on your frontend using the stack yeoman sets up for you. By keeping the frontend isolated from the backend you get an amazingly fast development environment and draw a clear line between backend and frontend (great for making sure you are writing the right unit/integration tests). Yeoman sets up the test environment for you using jasmine as the testing library and karma as the runner. karma is possibly the fastest and most complete js test runner out there. And it is very well integrated with angular.
The experience of coding with Livereload is simply amazing. Immediate feedback for every little addition you save in your code editor while you are working, without having to reload the page in the browser!
Rails was born in the request-response era of the web, and it shows. Yeoman sets up an environment with defaults that are better suited for developing web applications.
rvm use 1.9.3 git clone https://github.com/EmmanuelOga/simple-angular-rails-app.git cd simple-angular-rails-app bundle install bundle exec rake db:migrate bundle exec rails s -p 3000
NOTE: the angular application was generated using these commands.
npm install -g yo generator-angular mkdir ngapp; cd ngapp yo angular notes
nvm use 0.10.13 cd simple-angular-rails-app/ngapp npm install -g grunt-cli npm install bower install grunt server # opens a browser window... you are done!
During development, you need to run both rails and the grunt server. The grunt server takes care of serving the assets (yes, it can serve coffeescript if you like that) and doing the live reloads.
We simulate that the whole environment is a single web application by running a proxy inside the grunt server. At some point during the production deploy process we'll be consolidating the whole angular app as a set of static assets in rails' public/ folder.
Here's a diagram of the stack during development:
Would it make sense to go the extra mile and just host the angular app and the rails backend as separated processes? It would. But this setup allows you deploy the whole thing as a single app in the end, and have everything in a single domain easily.
The grunt server task proxies any url with path /api to the rails backend on localhost:3000.
Would sinatra be a better choice for such a small app? It would... but the whole point of this blog post is to show a possible way of using angular and rails together. This setup should be usable if you already have a running rails app and you want to add some additional single-pagy parts to it.
To run both the backend tests and front end tests, you can run:
rake test PHANTOMJS_BIN=`which phantomjs`
This is done by reopening rails's test task and adding a step to run the karma runner. This design is a bit simplistic but it works. You may want to have something a bit more elaborate to make it so angular's tests are run even if rails tests fail to complete.
The PHANTOMJS_BIN env var is needed because the project configures karma to use phantom js, but it could be changed to run any other browser.
karma can be configured to watch the tests as opposed to do a single run. You should deffinitively look into that during development.
If you run
grunt build, grunt will package the whole angular app in a
tidy package on the rails public/ folder. This packaging step could
happen in the server to avoid having to commit the generated assets in
your repository, analogous to how it is done for generating assets with
rails' assets pipeline.
The rails app sets the XSRF token in the cookies. The cookies are accessible even when using the proxy because the port is not taken into account when restricting access to the cookies.
Check ApplicationController for some notes on the XSRF protection.