AngularJS and Ruby on Rails work together

Finding the best integration of AngularJS and Ruby on Rails

Recently I got really excited with AngularJS so to make it work perfectly with Ruby on Rails there are some configurations needed. There are available blog posts on how to integrate it perfectly but somehow I wasn’t happy with the available preferences. Some offered to add the javascript files manually to the project and to manual project organization, others offered some kind of gem packager or even automated as a rails app template.

My goal is to describe how to start new rails app project from the scratch but the instructions should be succinct enough to be able to reuse them for the existing project (Actually I did extract it from the existing application I am working on). For the front end development I recently discovered great gem that really can make it more closer to pure full stack javascript development.
Bower is a great javascript package manager by the people who are working on Twitter Boostrap. It is like Bundler but made for javascript instead of ruby language. When I found out that there is a ruby gem that is integrated with rake tasks so I can easily update all javascript libraries without needing adding gem library for each one. The gem is called bower-rails.

My initial plan is to evolve this post into a series of blog posts on how to develop a fully functional demo application so I’ve included some steps that are might not needed but are good to have. Don’t worry I will provide explanation why I am using each of them.
Here is my plan what I will try to achieve with this series of posts:

  • creating a new demo project with angularJS from scratch, showing all my changes along the way, and trying to explain every step. this will include creating basic rails 4 app
  • adding basic gems
  • setup front end development with Bower
  • adding angularJS
  • implementing basic Rails and AngularJS controllers

Prerequisites

In this post we will use some of the predefined versions of  libraries to make it work.

  • Mac OS Yosemite operating system, though it shouldn’t be much different for *nix environment.
  • Ruby 2.1.3
  • Ruby on Rails 4.1.6
  • AngularJS 1.3.0
  • Postgresql
  • Nodejs
  • Bower
  • Haml for writing views
  • Sass for styling views
  • Your favorite code editor. I am using Sublime text editor but any you feel comfortable is good enough

Initializing the new Rails 4.1.6 app

Probably you know this step already. Everyone uses them to start new rails project. We will call this application todo and use few flags to change default settings for the test framework and use Postgresql database.

rails new todo --skip-test-unit --skip-bundle --quiet --database=postgresql

We are intentionally skipping building a bundle for now until we add additional gems to the Gemfile, configure the database and make sure we have a clean slate base on which we are going to work on.

HINT: We all are sometimes lazy so it is good to put all these arguments into ~/.railsrc file so every time you run new generator it will reuse them without needing to write them all:

-B #Skip Bundle
-T #Skip Test-Unit
-d postgresql #Use postgres

now let’s continue…

<span style="background-color: #f9f9f9;">cd todo</span>

General gems that are good to have

There are usually a handful of gems that I usually add to my new project and I will go little bit in details. First of all we will need to remove turbolinks gem from the Gemfile since it doesn’t fit the usage inside the single page application. Here are the following gems we will add:

  • Common gems that are related to make develop with ease. So let’s add following lines to Gemfile
    # use haml for generators as default templating
    gem 'haml-rails'
    # better form building
    gem 'simple-form'
    # list of countries for country dropdown
    gem 'country_select'
    # nested forms
    gem 'nested_forms'
    # great addition to sass/scss functionality
    gem 'compass'
    # advanced error page for development environment, with ruby shell
    gem 'better_errors'
    gem 'binding_of_caller'
    # don't show asset requests in development log file
    gem 'quiet_assets'
    # making your controllers inherit all restful actions
    gem 'responders'
    # powerful alternative to the IRB
    gem 'pry'
  • We have disabled default testing framework since I usually use RSpec and Capybara with Selenium for browser based testing of features.
    group :test, :development do
      gem 'rspec'
      gem 'rspec-rails', '~> 2.0'
      gem 'factory_girl_rails', '~> 4.0'
      gem 'capybara'
      gem 'database_cleaner'
      gem 'selenium-webdriver'
    end
  • To make it work with AngularJS I will also add two gems that are meant to support javascript libraries.
    gem 'bower-rails'
    gem 'angular-rails-templates'
    

    I’ve already described the bower-rails gem that giver you the power of Bower inside rails project. Angular-rails-templates gem is another one that makes rails working with angular templates much easier. It creates a cache of templates that doesn’t require AJAX requests for each template.

If some gems are not descriptive enough please do google them and read all the functionality they offer. So here is the full Gemfile file content.

source 'https://rubygems.org'


# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.6'
# Use postgresql as the database for Active Record
gem 'pg'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# great addition to sass/scss functionality
gem 'compass'

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer',  platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0',          group: :doc

# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring',        group: :development

group :development do
  gem 'quiet_assets'
  gem 'better_errors'
  gem 'binding_of_caller'

  gem 'meta_request'

  gem 'letter_opener'

  gem 'rb-fsevent', require: false
  gem 'terminal-notifier-guard'

end

group :test, :development do
  gem 'rspec-rails', '~> 2.0'
  gem 'shoulda-matchers'
  gem 'factory_girl_rails'
  gem 'hirb'
end

group :test do
  gem 'email_spec'
  gem 'cucumber-rails', require: false
  gem 'guard-cucumber'
  gem 'database_cleaner'
  gem 'launchy'
  gem 'capybara'
  gem 'capybara-webkit'
  gem 'headless'
  gem 'faker'
  gem 'forgery'
  gem 'rack-test'
end

# AngularJS support
gem 'bower-rails'
gem 'angular-rails-templates'

# use haml for generators as default templating
gem 'haml-rails'
# better form building
gem 'simple_form'
# list of countries for country dropdown
gem 'country_select'
# nested forms
gem 'nested_form'
# advanced error page for development environment, with ruby shell

# making your controllers inherit all restful actions
gem 'responders'
# powerful alternative to the IRB
gem 'pry'

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Use debugger
gem 'byebug', group: [:development, :test]

One things I dislike being generated

When you generate new project by default generator for models, controllers etc. usually generate a bunch of unnecessary files like helpers, stylesheets, javascript files that are dependent on the domain so to disable them we add the following code to the ./config/application.rb:

config.generators.stylesheets = false
config.generators.javascripts = false
config.generators.helper = false

Configure database.yml and example database file

Since Ruby on Rails 4.1 you have new file called secrets.yml that can be used for adding private informations like database access information. So let’s modify it to be able to deploy project to repository without exposing private information.
First we add to ./.gitignore file exception not to include secrets.yml file

config/secrets.yml

And make an example copy file for secrets template

cp config/secrets.yml config/secrets.yml.example

Now you can add details to secrets for username and password for database connection. Rewrite database.yml file to look like:

default: &default
  host: <%= Rails.application.secrets[:database][:host] %>
  adapter: postgresql
  encoding: UTF8
  database: <%= Rails.application.secrets[:database][:name] %>
  pool: 10
  reaping_frequency: 30
  username: <%= Rails.application.secrets[:database][:username] %>
  password: <%= Rails.application.secrets[:database][:password] %>

development: *default
test: *default
production: *default

And now inside secrets.yml.example file add the missing fields like:

development:
  secret_key_base: 2f040beb7605141a4b10a68a1121ea476cc5e86bd837bff2b9925144f013ece49c71816be0d24c721d8f9aa70519cb5c80abe3b0ffb01e12a13e6d8dc59400ab
  database:
    :host: localhost
    :name: todo_development
    :username: root
    :password: password

test:
  secret_key_base: 9bb840e19afc8215aa989ee9a98e5a176f6006ce5c1fcbdc322847b6d2b57d826031996d6115675917142f3cb66186501f858aa6c0b7c308024343a07409cc71
  database:
    :host: localhost
    :name: todo_test
    :username: root
    :password: password

# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
  database:
    :host: localhost
    :name: todo_production
    :username: root
    :password: password

Bower and front end dependency management

There is not any provided way from rails directly to manage front-end libraries and extensions that are not deployed as a gem. Tricking them and packaging them into gem as they would represent Rails Engines which are really not. We are going to use Bower to manage front-end resources for javascript supported front end development.
Here is the bower-rails gem that will merge the usefulness of only javascript full stack development and the development with rails. Prerequisite for this gem is that we have already installed npm (node package manager) that it is part of the node. Besides node library we also need to install bower library. Easiest way to install it is through homebrew, here is the following command to install them both

brew install node && npm install bower

For more details please read documentation for homebrew and npm

Let’s bundle the gems

Run bundle install to install all the required ruby gems for our project.

Now when you see that all are successfully built let’s add all the front-end library dependencies with Bower. To install dependencies to directories let’s run the initializer to generate custom bower.json

rails g bower_rails:initialize json

We can also run rails g bower_rails:initialize that will generate Bowerfile file that has similar syntax as Bundler’s Gemfile but for this tutorial I will rather use the same syntax with json file that is being used in javascript development.

Let’s add angularjs and angular route dependency for javascript to ./bower.json

{
  "lib": {
    "name": "bower-rails generated lib assets",
    "dependencies": {
      "angular": "latest",
      "angular-route": "latest"
    }
  },
  "vendor": {
    "name": "bower-rails generated vendor assets",
    "dependencies": {
    }
  }
}

and run following command to install them

rake bower:install

Now when we have installed resources we can add the required javascript files to application.js file which should look like this.

//= require jquery
//= require jquery_ujs
//= require angular
//= require angular-route
//= require angular-rails-templates
//= require_tree .

Let us make a folder where we will hold all the templates

mkdir app/assets/templates/

Now before trying out if everything works as needed there are few more steps to finish. First we need to remove all turbolinks references in application layout file app/views/layouts/application.html.erb:

 <%= stylesheet_link_tag 'application', media: 'all' %>
 <%= javascript_include_tag 'application' %>
 <%= csrf_meta_tags %>

Next step to do is to create database for the project

rake db:create

We can try to run server for the first time and check if everything is running okay.

rails server

If we visit http://localhost:3000/ in your favorite web browser you should see the following screen:

Initial rails screen without routes
Initial rails screen without routes

YES So we did it 🙂 We have everything working as it should be with no errors. If you get any problems don’t hesitate to comment below.

First AngularJS page

We don’t stop just adding all the resources without writing at least a small angularjs page to show that it works as it should be working.

Add new route to ./config/routes.rb file:

Rails.application.routes.draw do
  root 'home#index'
end

And a accompanying controller with generator rails g controller Home index

class HomeController < ApplicationController
  def index
  end
end

We need to add barebones AngularJS app so we will put this into app/assets/javascripts/app.js file

var todo = angular.module('todoApp', []);

Last thing we need to do is to add some content to the index.html.haml page

.container-fluid{ 'ng-app' => 'todoApp'}
  .panel.panel-success
    .panel-heading
      %h1{ 'ng-if' => 'name' } {{name}}
    .panel-body
      %form.form-inline
        .form-group
          %input.form-control{ type: 'text', placeholder: 'Enter your name', autofocus: 'autofocus', 'ng-model' => 'name'}

Now if you go back to the browser and refresh the page you should see the text input field. Try to write something in it should show an updated text above the field.

So here it is. We have not just added few simple javascript files to the rails pipeline but prepared a full project for front-end and back-end development where we can easy introduce the whole projects that we’ve been playing with javascript only.

Final version of the demo project should be similar to the following code on the github

  • olzel

    Thanks! Tutorial works fine, there is only one misspelling in the code of
    application.js here : “//= require angular-rails-template” -> WRONG “//= require angular-rails-templates” -> RIGHT! the letter “s” has to be placed
    .. ah 2 misspellings more … “should-matchers” -> “shoulda-matchers” && “bye” -> “byebug” (now?!)

    • thorsson

      Thank you for reminding me of my typos. I hope you will do something great with rails+angular 😉