ApiClient

Gem Version Build Status Dependency Status Coverage Status Code Climate

ApiClient handle all the logic necessary to call Some API, catch the response and initialize an object with it for you. It is possible to use Typhoeus or the native Ruby Library Net::Http. It works very well with rails, so you can exchange your ActiveRecord based models without any concern and your application will make Api calls transparently. It supports ruby 1.8.7, 1.9.2, 1.9.3, jruby and ree out of the box.

Useful Links

Mailing List

If you have any questions, comments, or concerns, please use the Google Group instead of the Github issue tracker:

https://groups.google.com/forum/#!forum/zertico-api-client

Documentation

You can find the code documentation for the last version generated by Yard on this link:

http://rdoc.info/gems/api-client/frames

Changelog

https://github.com/zertico/api-client/blob/master/CHANGELOG.md

Installation

Add this line to your application's Gemfile:

gem 'api-client'

And then execute:

$ bundle

Or install it yourself as:

$ gem install api-client

If you will use Typhoeus (https://github.com/typhoeus/typhoeus), you must have Typhoeus version above 0.5.0.

Basic Usage

Create an initializer:

ApiClient.configure do |config|
   # You can define an api entry point
   config.path = 'http://api.example.com'
   # or several ones
   config.paths = { :default => 'http://api.example.com', :auth => 'http://auth.example.com' }
   # Default header
   config.header = { 'param1' => '123329845729384759237592348712876817234'}
   # Basic Auth
   config.basic_auth('user', 'pass')
   # If inside Rails
   config.mock = Rails.env.test?
end

Add this to your ApplicationController:

rescue_from ApiClient::Exceptions::NotFound, :with => :not_found

def not_found
    #Specify your own behavior here
end

You can define a more generic rescue that will work for any error:

rescue_from ApiClient::Exceptions::Generic, :with => :generic_error

On Your model, extend ApiClient::Base

class User < ApiClient::Base

Then, on your action, just put into it:

@user = User.get(3)
#or
@user = User.find(3)

where 3 is the id of the user.

To a request that returns a collection of the object, use:

@user = User.collection
#or
@user = User.all

Advanced Usage

ApiClient can read api responses with root nodes based on the name of the virtual class. In Some cases, that is not the required behavior. To Redefine it, use remote_object method:

class Admin < ApiClient::Base
    self.root_node = 'user'
end

To specify a resource path different from the expected, you can overwrite the behavior by setting resouce_path:

class Admin < ApiClient::Base
    self.resource_path = 'users?type=admin'
end

It can handle associations. It will automatically instantiate an association for you if properly setted like below:

class Person < ApiClient::Base
    self.associations = { :houses => "House", :cars => "Car" }
end

In case you need to work with one api entry point, it will define you path as the default. If you need multiple entry points, you must define a name to each one, so you can refer to them on the model as:

class User < ApiClient::Base
    self.path = :auth
end

This code will create a setter and a getter for houses and cars and initialize the respective class.

When you are working with collections you can use api pagination according Hal Specification (http://stateless.co/hal_specification.html) . You just need to pass a hash as:

{
  total: 10,
  total_pages: 1,
  offset: 10,
  _links: {
    first: { href: "/api/clients" },
    previous: null,
    self: { href: "/api/clients" },
    next: null,
    last: { href: "/api/clients?page=1" }
  },
  users: [ { user: { name: "example1" } }, { user: { name: "example2" } } ]
}

Since version 2.0.0, it is possible to make api calls from the object. The syntax is pretty much the same. It will make the call and update the fields with the response. Look at the examples folder to see more code examples

Testing

Set mock config variable as true inside yout spec_helper or test_helper:

ApiClient.configure do |config|
   config.mock = true
end

With this setting no requisitions will be made. All calls will just return a new object with the attributes received.

Parallel

When making parallel requests, the requests are made in threads, so to get the response it is necessary to specify an initialized object to update when the requisition is complete.

@users = ApiClient::Collection.new({}, User)
@cars = ApiClient::Collection.new({}, Car)
@house = House.new

ApiClient.parallel do
    User.all.on_complete_update(@users)
    Car.all.on_complete_update(@cars)
    House.find(1).on_complete_update(@house)
end

Migrating from 2.*.* to 3.0.0

Since version 3.0.0 is not necessarily set the root_node on the attributes when calling methods on the class.

Before:

@user = User.create({ :user => attributes })

After:

@user = User.create(attributes )

More Examples

Project

TODO

  • Add more Response Handlers

Mantainers

@plribeiro3000

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request