Build a simple ruby API client using Spyke

Today we'll explore a young but promising gem that will help you building ruby API client as a gem. It's called Spyke and it's awesome!

Whenever you build a new API, you need to build a new client acting as a consumer for your applications to install and start interacting with your API. You've probably heard of Her, a ruby gem working like ActiveRecord but with the HTTP protocol in mind. Sadly, the gem is stuck in many opened issues and un-merged commits :(

Introducing Spyke

Interact with REST services in an ActiveRecord-like manner.

I think this state is missing two really important keywords regarding the gem: simplicity and conventions.


Let me show you how simple it is to setup Spyke to start interacting with an existing API (or a brand new one) by building a new ruby client as a gem.

We'll assume you have a users resource with simple CRUD actions defined:

GET /users/  
POST /users  
GET /users/1  
PUT /users/1  
DELETE /users/1  

Start by creating a new gem using bundler:

bundle gem consumer  

Edit the consumer.gemspec file to install Spyke:

spec.add_dependency 'multi_json'  
spec.add_dependency 'spyke'  
spec.add_dependency 'faraday'  

and run the bundle command.

We'll initialize the Spyke connection in consumer/consumer.rb with the following code:

require 'faraday'  
require 'spyke'  
require 'consumer/json_parser'

module Consumer  
  Spyke::Base.connection = '') do |c|
    c.request :json
    c.use Consumer::JsonParser
    c.adapter Faraday.default_adapter

Notice that I used a class named Consumer::JsonParser. Spyke expect your API response to have a JSON formatted like this:

  data: [{}, {}, ...],
  metadata: {},
  errors: {}

If your API already returns the following format, you can go ahead and remove the json_parser references. Otherwise you'll need to implement your own custom parser matching your API json response format. For example my json parser is defined in consumer/json_parser.rb and look like this:

require 'faraday'  
require 'multi_json'

module Consumer  
  class JsonParser < Faraday::Response::Middleware
    def parse(body)
      json = MultiJson.load(body, symbolize_keys: true)
        data: json[:data],
        metadata: json[:meta],
        errors: json[:errors]
    rescue MultiJson::ParseError, TypeError => e
      { errors: { base: [error: e.message] } }

Now it's time to add our User model. Add the following code in a file called user.rb under consumer/:

module Consumer  
  class User < Spyke::Base
    uri 'users/(:id)'

and don't forget to require the file after the other requires in consumer/consumer.rb:

# spyke and faraday require here...
require 'consumer/user'  

That's it! Start your API server and launch a new ruby console to see it in action:

bundle exec irb -r 'consumer'  
> Consumer::User.all.count
 => 250
> Consumer::User.all.first
 => #<Consumer::User(...) id: "1" email: "[email protected]">
> user = Consumer::User.find(1)
 => ...
> user.update_attributes(email: [email protected]')
 => true
> user.destroy
 => true

What we've learn

Today we implemented a ruby client consuming an existing API exposing simple CRUD actions using Spyke gem. We saw how easy it was to setup the gem and start interacting with our API from the ruby console.

Spyke use Faraday under the hood allowing us to plug & play any Faraday Middleware out there. Thinking of HTTP cache techniques so stay tune to hear about it in a future article.

Show Comments