ben tedder : code things

Starting an Angular 4 app on Rails 5 from scratch

This will run you through setting up an angular app on a Rails 5 server from scratch.

Prequisites

  • Assuming you have node + npm locally
  • Install the Angular CLI tool (npm install -g @angular/cli)
  • Install the Rails gem (gem install rails)

1. Install Rails

Create a new directory called myapp, create a new rails project in it, and start up the rails server:

mkdir myapp
cd myapp
rails new .
rails s

Navigate to http://localhost:3000 to see your new rails server

2. Install Angular

From inside your rails directory run ng new angular, where angular is the name of your app. Note that the name app is already taken by Rails. Once it is installed run ng serve to spin up the angular app.

cd myapp
ng new angular
cd angular
ng serve

Navigate to http://locahost:4200 to see your new angular app

3. Let Angular talk to Rails

A this point you now have an angular app running on port 4200 and a rails app running on port 3000. This is great...but in order to do any kind of communication we need to allow cross-origin requests from Rails when we're in development.

Note: this tutorial is just covering developing in Rails and Angular. A follow-up post will walk through the steps to get this working in production

In order to let angular (on port 4200) talk to the API you're going to create in Rails (on port 3000), we need to enable CORS.

Add the following to your gemfile, kill the rails server, run bundle install again, and restart your rails server.

gem 'rack-cors', :require => 'rack/cors'

Before this works we need to add one more thing to Rails (only in dev). Create a file at config/initializers/cors.rb and add the following:

Rails.application.config.middleware.use Rack::Cors do
  allow do
    origins '*'
    resource '*',
    :headers => :any,
    :expose  => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
    :methods => [:get, :post, :options, :delete, :put]
  end
end

This allows anybody to request anything (hence why we're just in dev) from any location.

Note: Stating again that this is a development only solution.

Ok, so at this point now Rails should be able to handle any request we send it from Angular on port 4200. For a proof of concept, let's set up a route that returns some json. We'll use the rails generator for a new controller.

rails g controller Users

This creates a file at app/controllers/users_controller.rb.

Create a method to return some json:

class UsersController < ApplicationController
  def list_users
    render json: { users: [{ name: 'Michael' }, { name: 'Dwight' }] }
  end
end

Let's add a route to hit this method in config/routes.rb:

Rails.application.routes.draw do
  get 'users', to: 'users#list_users'
end

To make sure everything is working, go to http://localhost:3000/users and verify the json is structured like you expect.

If everything looks good, let's setup Angular to read from this endpoint.

4. Angular setup

The next thing we need to do is setup Angular to hit our endpoint and get back the json response, rendering the list of users to the screen.

Navigate to angular/src/app/app.component.ts and replace the file with the following code:

import { Component } from '@angular/core';
import { Http }      from '@angular/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users = [];
  constructor(private http:Http) {
    this.getUsers();
  }

  getUsers() {
    this.http.get('http://localhost:3000/users')
             .subscribe(res => {
               this.users = res.json().users;
             });
  }
}

And then in app.component.html add the following div:

<div *ngFor="let user of users">{{ user.name }}</div>

This performs a basic injection of the Http module and calls a get on the users route we creatd earlier. If everything is hooked up correctly, you should see the array of users displayed in the browser.

Wrap-up

This tutorial is obviously lacking in a few areas:

  • Never put the CORS config into production
  • ng build should eventually place your compiled code into a place that is consumed by a route in rails to load your actual app
  • Calling the Http method would normally be done by a service. This is meant as a quick up-and-running tutorial.

Hopefully this at least gets your environment up and ready to develop on Angular. Once you're ready to push this code to production you'll need to do a bit more config, but don't let that stop you now. It's just a matter of figuring out where the files live and where the api endpoints live.