Rails provides an excellent backend for your Javascript front-end framework.
Why Rails?
Rails is a great lightweight, powerful server-side solution. You can add your front-end framework on top of it.
The Rails motto is “convention over configuration”. Rails provides a set of standards that the community has agreed upon as best practice. So if another Rails dev is checking out your app, it’s easier to get up and running.
Rails allows you to scaffold apps very quickly so it’s great for startups. It’s relatively painless to roll out a prototype.
- e.g.- AirBnB, Hulu, Twitter, Blue Apron, Plated, Daily Burn, GA website, Robinhood FAQ, Death Wish Coffee (Intuit Super Bowl Ad)
Rails is “auto-magical”, which can be good or bad.
- GOOD - rapid prototyping
- BAD - Sometimes you don’t always know what’s going on under the hood, but as long as you play in their sandbox you’re ok (e.g.- use their helper methods, sset pipeline, etc).
Rails API
You may also use Rails for API-only Apps and scaffold a project with no views. This would allow you to host Rails on one server and your front end on another. This makes for an extremely lightweight Rails app since it takes out any middlewares and extra cruft that the views would normally use.
For a clunky analogy… the Rails API would be like a hard-top convertible in that we can completely remove the views. A soft-top convertible is like scaffolding a standard Rails app but ignoring the views (even though the functionality is always available).
Add Angular to a Rails app
- CDN
- Download angular files
- Ruby Gem
- Bower (what we’re using tonight)
Rails App Code Along
Completed code for this article can be found here. Credit goes to this excellent Angular-Rails tutorial. It was my reference for the initial Bower implementation.
1) rails new books -T --database=postgresql
This command will create a new rails project + directory called books. -T
tells Rails not to scaffold a test suite. --database=postgresql
will automatically bundle the gem pg
so we may use a PostgreSQL database. By default Rails uses SQLite.
2) cd books && bin/rake db:create
This will cd
into the project directory and create our database. Rake is Ruby Make, a standalone Ruby utility used for common administration tasks, especially sophisticated ones that build off of each other.
3) At this point, we can start our Rails server with rails server
and checkout the welcome page at http://127.0.0.1:3000
Add and configure Angular + Bootstrap using Bower
Bower was created by Twitter specifically to manage front-end assets. We’ll use it to set up our front-end packages and dependencies.
4) Add gem 'bower-rails'
to the Gemfile
. From the command line, run bundle install
to add the library.
Ruby gems are similar to npm modules, the Gemfile is similiar to package.json and bundle install is very similar to npm install
5) Next, on the command line, run touch Bowerfile
. This will create a Bowerfile
in the root of the project. Then add the following to that file:
# This will add Angular and Bootstrap-Sass
asset 'angular'
asset 'bootstrap-sass-official'
6) Run rake bower:install
Bower installs dependencies in vendor/assets/bower_components
. The Rails asset pipeline dictates that 3rd party code lives in the vendor
directory.
7) Let’s add the Angular require paths to app/assets/javascripts/application.js
. Turbolinks is a gem that uses Ajax to speed up page rendering in most applications. We’ll remove turbolinks since it can hinder performance for front-end frameworks. Your requires should look like so:
//= require jquery
//= require jquery_ujs
//= require angular/angular
//= require_tree .
8) Let’s import our bootstrap stylesheets in app/assets/stylesheets/application.css.scss
beneath all of the comments. Also, be sure to add the .scss
extension to the file name so it will @import
correctly:
@import "bootstrap-sass-official/assets/stylesheets/bootstrap-sprockets";
@import "bootstrap-sass-official/assets/stylesheets/bootstrap";
Add a doorway route for our Angular app
9) Add root 'home#index'
to routes.rb
. This will be the main route that will serve as the doorway to our Angular app.
10) Let’s create a controller for that route. Create app/assets/controllers/home_controller.rb
and add:
class HomeController < ApplicationController
def index
end
end
Instantiate our Angular App
11) For this demo we’re gonna use a Book Model so we’ll call this our bookApp. Let’s create app/assets/javascripts/app.js
and add code to instantiate our Angular app:
angular.module('bookApp',[])
.controller('BooksController', BooksController);
function BooksController() {
var vm = this;
vm.names = ["Marc", "Maren", "Diesel"]
}
We’re using var vm
here for view model. I’ve also included some dummy data to make sure our view is wired up correctly.
Create a view
12) Create app/assets/views/home/index.html.erb
and add:
<div class="container-fluid" ng-app="bookApp">
<div class="panel panel-success">
<div class="panel-heading">
<h1 ng-if="name">Hello, {{name}}</h1>
</div>
<div class="panel-body">
<form class="form-inline">
<div class="form-group">
<input class="form-control" type="text" placeholder="Enter your name" autofocus ng-model="name">
</div>
</form>
</div>
</div>
<div class="panel panel-success" ng-controller="BooksController as ctrl">
<div class="panel-heading">
<ul ng-repeat="book in ctrl.names">
Hello, {{book}}
</ul>
</div>
</div>
</div>
You could also add ng-app
to the body
tag in app/assets/views/layouts/application.html.erb
. Then our entire app would belong to booksApp
.
13) We can start up our rails server
and go to localhost:3000
to make sure that Angular is working.
Create the Book model + add some seed data
14) rails g model Book title author
We’ll create a model for Book with title and author fields (both Strings, by default)
15) Let’s add some seed data to db/seed.rb
to populate our database:
Book.destroy_all
Book.create([
{title: "50 Shades", author: "Schmitty"},
{title: "Lawyer Books", author: "Grisham"},
{title: "The Hunger Games", author: "Collins"},
{title: "JS Good Stuff", author: "Crockford"}
])
16) From the command line run rake db:migrate db:seed
This will create our schema file and seed our database
Set up our REST-ful api endpoint to serve the JSON
17) Add a route to our app/config/routes.rb
file under our root
route.
get '/books' => 'books#index'
A route consists of the HTTP verb, the URL and the controller/action.
18) Eventually, we’re gonna use $http.get
in our Angular controller to grab our data. Let’s create a controller to handle the JSON data from our API. Create a file in app/assets/controllers/books_controller.rb
. Then, let’s make all the books available via JSON in our BooksController
index action:
class BooksController < ApplicationController
def index
@books = Book.all
end
end
19) We’re gonna use jbuilder to serve our books API data. Let’s create app/assets/views/books/index.json.jbuilder
and add:
json.array!(@books) do |book|
json.extract! book, :id, :title, :author
end
20) Now we can start our server rails server
and go to http://localhost:3000/books.json
(try it in a new window) to see that Rails is serving our data as JSON.
Consume the data with Angular
21) Let’s add some code to grab all the books from our endpoint in app/assets/javascripts/app.js
angular.module('bookApp',[])
.controller('BooksController', BooksController);
function BooksController($http) {
var vm = this;
vm.names = ["Marc", "Maren", "Diesel"];
vm.books = getBooks().success(function(data){
vm.books = data;
});
function getBooks(){
return $http.get('http://localhost:3000/books.json');
}
}
We’ll add a getBooks() function to grab all the books from our REST-ful endpoint. We’ll assign the results of that function to the variable vm.books
. Also, don’t forget to inject $http
into BooksController
.
Update our view
22) Let’s go to our app/assets/views/home/home.html.erb
page and make some small tweaks. First, we’ll adjust our ng-repeat
so it repeats our vm.book
variable. We’ll also add some code to render the title
and author
of each book. Here’s the code for our ul
:
<ul ng-repeat="book in ctrl.books">
Title: {{book.title}} </br>
Author: {{book.author}}
</ul>
Conclusion
I really love Rails. It’s great to pair the rapid prototyping ability of Rails with an Angular front-end!