Class: HttpMagic::Api

Inherits:
BasicObject
Defined in:
lib/http_magic/api.rb

Overview

A magical class that interacts with HTTP resources with a minimal amount of configuration.

Assuming an api where the url www.example.com/api/v1/foo/99 responds with the following.

Header:

Content-Type: application/json

Body:

{
  "name": "Foo Bar"
}

Example

class ExampleApi < HttpMagic::Api
  url 'www.example.com'
  namespace 'api/v1'
  headers({'X-AuthToken' => 'token'})
end

ExampleApi.foo[99].get['name']
=> "Foo Bar"

ExampleApi.foo.create.post(name: 'New Foo')
=> { 'name' => 'New Foo' }

Direct Known Subclasses

PivotalTracker

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, namespace, headers) ⇒ Api

Returns a new instance of Api.



117
118
119
120
121
# File 'lib/http_magic/api.rb', line 117

def initialize(url, namespace, headers)
  @uri = Uri.new(url)
  @uri.namespace = namespace
  @headers = headers
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(part, *args, &block) ⇒ Object

Instance scoped method_missing that accumulates the URN parts used in forming the URI. It returns a reference to the current instance so that method and [] based parts can be chained together to from the URN. In the case of ExampleApi.foo the ‘foo’ method is accumlated as a URN part that will form the resulting URI.



228
229
230
231
# File 'lib/http_magic/api.rb', line 228

def method_missing(part, *args, &block)
  @uri.parts << part.to_s
  self
end

Class Method Details

.headers(value = :not_provided) ⇒ Object

Sets or returns the request headers for an HttpMagic based class. The headers will be passed along to each resource request being made.

Example

class ExampleApi < HttpMagic:Api
  url 'www.example.com'
  headers({'X-AuthToken' => 'token'})
end


55
56
57
58
59
60
# File 'lib/http_magic/api.rb', line 55

def self.headers(value = :not_provided)
  unless value == :not_provided
    @headers = value
  end
  @headers
end

.method_missing(name, *args, &block) ⇒ Object

Class scoped method_missing that starts the magic of creating urns through meta programming by instantiating an instance of the class and delegating the first part of the urn to that instance. This method is an implementation of the Factory Method design pattern.



113
114
115
# File 'lib/http_magic/api.rb', line 113

def self.method_missing(name, *args, &block)
  new(@url, @namespace, @headers).__send__(name, *args)
end

.namespace(value = :not_provided) ⇒ Object

Sets or returns the namespace for an HttpMagic based class. The namespace will be prefixed to the urn for each request made to the url.

Assuming an api where each resource is namespaced with ‘api/v1’ and where the url www.example.com/api/v1/foo/99 responds with the following.

Header:

Content-Type: application/json

Body:

{
  "name": "Foo Bar"
}

Example

class ExampleApi < HttpMagic:Api
  url 'www.example.com'
  namespace 'api/v1'
end

ExampleApi.foo[99].get['name']
=> "Foo Bar"


88
89
90
91
92
93
# File 'lib/http_magic/api.rb', line 88

def self.namespace(value = :not_provided)
  unless value == :not_provided
    @namespace = value
  end
  @namespace
end

.url(value = :not_provided) ⇒ Object

Sets or returns the uniform resource locator for the HTTP resource.

Example

class ExampleApi < HttpMagic::Api
  url 'www.example.com'
end


102
103
104
105
106
107
# File 'lib/http_magic/api.rb', line 102

def self.url(value = :not_provided)
  unless value == :not_provided
    @url = value
  end
  @url
end

Instance Method Details

#[](part) ⇒ Object

Resource index reference intended to allow for the use of numbers in a urn such as the following ‘foo/99’ being referenced by ExampleApi.foo. It can also be used to allow for HttpMagic methods to be specified for a urn such as ‘foo/get’ being referenced by ExampleApi.foo. Finally, it can be used for urn parts that are not valid Ruby methods such as ‘foo/%5B%5D’ being referenced by ExampleApi.foo.

  • part - a part of a urn such that ‘foo’ and ‘bar’ would be parts of the urn ‘foo/bar’.

Returns a reference to its instance so that urn parts can be chained together.



135
136
137
138
# File 'lib/http_magic/api.rb', line 135

def [](part)
  @uri.parts << part.to_s
  self
end

#deleteObject



140
141
142
143
144
145
# File 'lib/http_magic/api.rb', line 140

def delete
  request = Request.new(@uri,
    headers: @headers
  )
  request.delete
end

#getObject

Gets a resource from the URI and returns it based on its content type. JSON content will be parsed and returned as equivalent Ruby objects. All other content types will be returned as text.

Assuming an api where each resource is namespaced with ‘api/v1’ and where the url www.example.com/api/v1/foo/99 responds with the following.

Header:

Content-Type: application/json

Body:

{
  "name": "Foo Bar"
}

Example

class ExampleApi < HttpMagic::Api
  url 'www.example.com'
  namespace 'api/v1'
end

ExampleApi.foo[99].get
=> { "name" => "Foo Bar" }


173
174
175
176
177
178
# File 'lib/http_magic/api.rb', line 173

def get
  request = Request.new(@uri,
    headers: @headers
  )
  request.get
end

#post(data = {}) ⇒ Object

POST’s a resource from the URI and returns the result based on its content type. JSON content will be parsed and returned as equivalent Ruby objects. All other content types will be returned as text.

Assuming an api where each resource is namespaced with ‘api/v1’ and where the url www.example.com/api/v1/foo/create responds with the following when a ‘name’ is sent with the request.

Header:

Content-Type: application/json

Body:

{
  "name": "New Foo"
}

Example

class ExampleApi < HttpMagic::Api
  url 'www.example.com'
  namespace 'api/v1'
end

ExampleApi.foo.create.post(name: 'New Foo')
=> { "name" => "New Foo" }


207
208
209
210
211
212
213
# File 'lib/http_magic/api.rb', line 207

def post(data = {})
  request = Request.new(@uri,
    headers: @headers,
    data: data,
  )
  request.post
end

#put(data = {}) ⇒ Object



215
216
217
218
219
220
221
# File 'lib/http_magic/api.rb', line 215

def put(data = {})
  request = Request.new(@uri,
    headers: @headers,
    data: data,
  )
  request.put
end