Red Green Repeat Adventures of a Spec Driven Junkie

Rails API & Angular Number Generator

I hacked my way through setting up Angular services in my last two articles:

The goal is to understand how to get a simple Angular application to connect to web server. In this article, I will setup a Rails server to be the server endpoint for the Angular app.

Ruby on Rails Icon Angular Logo

Requirements

  • Install Docker Community Edition
  • Docker image for rails
    • $ docker pull andrewrgr/rails-init-api-rgr
  • docker image for angular
    • $ docker pull andrewrgr/angular-rgr
  • NumberGeneratorApp source code
    • $ git clone https://github.com/a-leung/angular-services

The Angular app, NumberGeneratorApp, will have one slight modification and then we will build the Rails server to support the Angular app.

Modifying Angular app

In the second article, the app was using the HTTP client to read from a JSON response from a file. This time, we will make just one change to that Angular app:

In the src/app/number-generator.service.ts file, change:

private _HTTPFileURL = 'assets/result.json';

to:

private _HTTPFileURL = 'http://localhost:3000/number';

Yes, this will be the only change needed in the Angular app.

Create Rails API server

Let’s create a new Ruby on Rails API app using the Docker image with the command:

$ docker run --mount type=bind,source=$(pwd),target=/rails_app andrewrgr/rails-init-api-rgr rails new number_generator_app --api --skip-coffee --skip-spring --skip-sprockets --skip-test
api Have the Rails server run in API mode only.
skip-coffee Do not include CoffeeScript, just use JavaScript.
skip-spring Do not include the Spring fast loader since this app will run in a Docker container.
skip-sprockets Do not include Sprokets, we just want to be in API mode only.
skip-test Do not include MiniTest, no testing for now, let’s get things working!

Add Endpoint

In a new Ruby on Rails app, there is only the / endpoint, which shows the default “Welcome to Rails” page.

Rails init page

We need another endpoint specifically for our Angular app, so we will create it by adding a new controller called: number_generator with command:

$ docker run --mount type=bind,source=$(pwd),target=/rails_app andrewrgr/rails-init-api-rgr rails generate controller number_generator

This command creates a new file at: app/controllers/number_generator.rb. Modify the file contents to be:

class NumberGeneratorController < ApplicationController

  def number
    render json: { value: 42000 }
  end
end

This will now return a JSON response to an endpoint, to connect this function to an endpoint, we have to modify the config/routes.rb file.

Configure Routes

To connect a Ruby on Rails’ server endpoint, so any requeests to /number will call the method number of the NumberGeneratorController, we have to modify the contents of the config/routes.rb file to be:

Rails.application.routes.draw do
  get '/number', to: 'number_generator#number'
end

This connects any brower request: localhost:3000/number to run the number method in the NumberGeneratorController.

Test Configuration

Let’s test out the application by running it:

$ docker run --mount type=bind,source=$(pwd),target=/rails_app -p 3000:3000 andrewrgr/rails-init-api-rgr rails s

Open a browser and goto: http://localhost:3000/number, the image will be:

image

Test curl

We can use another tool to test the server configuration is UNIX utility: curl, it’s a command line program that makes HTTP requests.

The command and output:

$ curl localhost:3000/number
{"value":42000}$

Connect Angular

With the Ruby on Rails app ready to accept requests at: http://localhost:3000/number, let’s have the Angular app connect to it.

Start the Angular server with:

$ docker run --mount type=bind,source="$(pwd)",target=/angular -p 4200:4200 andrewrgr/angular-rgr ng serve

If the Ruby on Rails is not running, start it with:

$docker run --mount type=bind,source=$(pwd),target=/rails_app -p 3000:3000 andrewrgr/rails-init-api-rgr rails s

And open a browser to: localhost:4200 and the page should be:

Angular CORS Error

What’s wrong? There’s no output. Looking at the browser’s console, we see:

Web Console CORS Error

Hmm… this is interesting. Looking at the console of the Ruby on Rails server, there is nothing… hmm…?

Configuring CORS

I realized that Ruby on Rails accepts any web request, but to prevent another website from using unauthorized resources, CORS was setup for webservers to prevent abuse.

I found the solution by configuring CORS, modify two files:

In the Gemfile, uncomment:

gem 'rack-cors'

In config/initializers/cors.rb file, uncomment and modify the file to be:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*',
    resource '*',
      headers: :any,
      methods: %i(get post put patch delete options head)
  end
end

Restart the server

Let’s restart the Ruby on Rails NumberGenerator server:

$ docker run --mount type=bind,source=$(pwd),target=/rails_app -p 3000:3000 andrewrgr/rails-init-api-rgr rails s

Test with CORS update

Once again, if the Angular app is not running, start the Angular app with:

$ docker run --mount type=bind,source="$(pwd)",target=/angular -p 4200:4200 andrewrgr/angular-rgr ng serve

Start the Ruby on Rails server with:

$ docker run --mount type=bind,source=$(pwd),target=/rails_app -p 3000:3000 andrewrgr/rails-init-api-rgr rails s

And open a browser to: localhost:4200 and the page should be:

Rails Angular Connect Success!

Yay!

Conclusion

Connecting a single page app based on Angular to a Ruby on Rails API server is pretty easy with all components in place.

The Ruby on Rails server needs to have CORS setting so any site can access it. In the article, I configured the Ruby on Rails server to be an API only server, but this is entirely optional.

With the properly configured Angular application, being able to connect to a web server required a single line change, which I think is sweet.