ApiClient
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
TODO
- Add more Response Handlers
Mantainers
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request