inf0rmer/blanket

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Blanket
[![Build Status](https://travis-ci.org/inf0rmer/blanket.svg?branch=master)](https://travis-ci.org/inf0rmer/blanket)
[![Coverage Status](https://img.shields.io/coveralls/inf0rmer/blanket.svg)](https://coveralls.io/r/inf0rmer/blanket?branch=master)
[![Code Climate](https://codeclimate.com/github/inf0rmer/blanket/badges/gpa.svg)](https://codeclimate.com/github/inf0rmer/blanket)
[![Inline docs](http://inch-ci.org/github/inf0rmer/blanket.svg?branch=master)](http://inch-ci.org/github/inf0rmer/blanket)


A dead simple API wrapper.

**Table of Contents**

- [Installation](#installation)
- [Usage](#usage)
    - [Quick demo](#quick-demo)
    - [How it works](#how-it-works)
    - [Responses](#responses)
    - [Request Parameters](#request-parameters)
    - [Headers](#headers)
    - [Extensions](#extensions)
    - [Handling Exceptions](#handling-exceptions)
- [Contributing](#contributing)

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'blanket_wrapper'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install blanket_wrapper

## Usage

### Quick demo

```ruby
require 'blanket'

github = Blanket.wrap("https://api.github.com")

# Get some user's info
user = github.users('inf0rmer').get
user.login
# => "inf0rmer"

# Get a user's repos
github.users('inf0rmer').repos.get
# => [{
#  "id": 20000073,
#  "name": "BAPersistentOperationQueue",
#  ...
# }]
```

### How it works
Blanket uses some metaprogramming black magic to wrap an API. Everytime you call a method on a wrapped API, Blanket appends it as a part of the final URL:

```ruby
github = Blanket.wrap("https://api.github.com")
github.users('inf0rmer').repos.get
```

Here's how the final URL is built, the step by step:

```ruby
github = Blanket.wrap("https://api.github.com")
# => "https://api.github.com"

github.users
# => "https://api.github.com/users"

github.users('inf0rmer')
# => "https://api.github.com/users/inf0rmer"

github.users('inf0rmer').repos
# => "https://api.github.com/users/inf0rmer/repos"
```

The final `get` method performs a GET HTTP request. You can also use it to append a final part to your request, so you can write something like:

As this magic works using `method_missing`, you can `send` slashed uri parts to the wrapper and it will play nicely. This is especially usefull when APIs give you URLs:
```ruby
github.get('users/inf0rmer/repos')
# or, if you don't wnat to perform the request yet, or have to append more parts to the uri
github.send('users/inf0rmer').repos#.get
```

```ruby
github = Blanket.wrap("https://api.github.com")
github.users.get('inf0rmer')
# => "https://api.github.com/users/inf0rmer"
```

### Responses
At the moment Blanket only accepts JSON responses. Every request returns a `Blanket::Response` instance, which parses the JSON internally and lets you access keys using dot syntax:

```ruby
user = github.users('inf0rmer').get

user.login
# => "inf0rmer"

user.url
# => "https://api.github.com/users/inf0rmer"

# It even works on nested keys
repo = github.repos('inf0rmer').get('blanket')

repo.owner.login
# => "inf0rmer"
```

If the response is an array, all `Enumerable` methods work as expected:

```ruby
repos = github.users('inf0rmer').repos.get

repos.map(&:name)
# => ["analytics-ios", "aztec", "fusebox", ...]
```

### Request Body
You can make requests with body using the `body` option:

```ruby
api = Blanket::wrap("http://api.example.org")
api.messages.post(body: 'Hello')
```

### Request Parameters
Blanket supports appending parameters to your requests:

```ruby
api.users(55).get(params: {foo: 'bar'})
# => "http://api.example.org/users/55?foo=bar"
```

You can also set default params for all your requests on initialization:

```ruby
api = Blanket::wrap("http://api.example.org", params: {access_token: 'my secret token'})
```

### Headers
HTTP Headers are always useful when accessing an API, so Blanket makes it easy for you to specify them, either globally or on a per-request basis:

```ruby
# All requests will carry the `token` header
api = Blanket::wrap("http://api.example.org", headers: {token: 'my secret token'})

# This single request will carry the `foo` header
api.users(55).get(headers: {foo: 'bar'})
```

### Extensions
Some APIs require you to append an extension to your requests, such as `.json` or `.xml`. Blanket supports this use case, letting you define an extension for all your requests or override it for a single one:

```ruby
# All request URLs are suffixed with ".json"
api = Blanket::wrap("http://api.example.org", extension: :json)

# Requests to "users_endpoint" are suffixed with ".xml" instead
users_endpoint = api.users(55)
users_endpoint.extension = :xml
```

### Handling Exceptions

Blanket will raise exceptions for HTTP errors encountered while making requests. Exception subclasses are raised for well known errors (404, 500, etc.) but for other status codes a default `Blanket::Exception` will be raised instead.

```ruby
begin
  api.thingamajig.get
rescue Blanket::ResourceNotFound => e
  e.code
  # => 404

  e.message
  # => "404: Resource Not Found"

  # The HTTP body, ie. the error message sent by the server
  e.body
  # => "Could not find this resource!"
end
```

## Contributing

1. Fork it ( https://github.com/inf0rmer/blanket/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request