Creating a Microservice Client Class
This guide walks explains how to create a new ActiveRecord model for integrating authorization in a Rails microservice application.
Guide Tasks
  • Read Tutorial

In this guide we'll create a Client class for our microservice so that applications attempting to communicate with the Notification service will need to be authorized. To begin we'll build a model test in RSpec.

touch spec/models/client_spec.rb

Creating the RSpec Tests

Now let's add a base case test for creating a new Client:

# spec/models/client_spec.rb

require 'rails_helper'

RSpec.describe Client, type: :model do
  describe 'creation' do
    it 'can be created' do
      client = FactoryGirl.build_stubbed(:client)
      expect(client).to be_valid
    end
  end
end

This is pretty basic, so I added a few components here, running rspec will give us some expected errors, first and foremost we don't have a model called Client so it renders the following:

large

Generating the Model

Let's fix this error by generating a model:

rails g model Client source_app:string api_key:string

Make sure to skip the default behavior of RSpec so it doesn't override our test by entering in n when it asks if we want to replace the test file. Now run bundle exec rake db:migrate to update the database schema. Now if you run rspec you'll see that we're back to green.

large

You may wonder how the tests are passing, because our test calls for a Client factory. If you look at the model generator you'll see that it actually created a factory for us automatically, which is a nice built in feature.

MacBook-Pro-3:message_service admin$ rails g model Client source_app:string api_key:string
Running via Spring preloader in process 25256
      invoke  active_record
      create    db/migrate/20160704214150_create_clients.rb
      create    app/models/client.rb
      invoke    rspec
    conflict      spec/models/client_spec.rb
    Overwrite /Users/admin/code/message_service/spec/models/client_spec.rb? (enter "h" for help) [Ynaqdh] n
        skip      spec/models/client_spec.rb
      invoke      factory_girl
      create        spec/factories/clients.rb

Let's update the values in the factory:

# spec/factories/clients.rb

FactoryGirl.define do
  factory :client do
    source_app "my_app"
    api_key "RbZHfHtD1h9XZvs4fGPJUgtt"
  end
end

I was able to get the api_key value by going into the rails console and entering in the command SecureRandom.base64.tr('+/=', 'Qrt'). This will be the command we use in our Client api_key_generator method so I wanted to use a value similar to what the app will actually use.

Implementing Validations

As you may have guessed we need to make sure that clients always have both values, so let's mark them as required. Let's add the tests into the model spec file:

# spec/models/client_spec.rb

  describe 'validations' do
    it 'can not be created if not valid' do
      client = FactoryGirl.build_stubbed(:client)
      client.source_app = nil
      client.api_key = nil
      expect(client).to_not be_valid
    end
  end

Let's get this test passing by adding the appropriate code in the model file:

# app/models/client.rb

class Client < ActiveRecord::Base
  validates_presence_of :source_app, :api_key
end

Now if we run the tests the tests are all back to green.

large

Let's make one small refactor and move the client = FactoryGirl.build_stubbed(:client) into a before block to remove the duplicate code.

# spec/models/client_spec.rb

require 'rails_helper'

RSpec.describe Client, type: :model do
  before do
    @client = FactoryGirl.build_stubbed(:client)
  end

  describe 'creation' do
    it 'can be created' do
      expect(@client).to be_valid
    end
  end

  describe 'validations' do
    it 'can not be created if not valid' do
      @client = FactoryGirl.build_stubbed(:client)
      @client.source_app = nil
      @client.api_key = nil
      expect(@client).to_not be_valid
    end
  end
end

Up Next

Ok, this is coming along nicely. With our Client class setup, in the next guide we're going to perform a slightly advanced task where we override the default ActiveRecord behavior and connect our Client and Notification models with a different foreign key than the id.

Resources