Class: Daylight::API

Inherits:
ActiveResource::Base
  • Object
show all
Includes:
AssociationPersistance, Associations, ReadOnly, Refinements
Defined in:
lib/daylight/api.rb

Overview

Daylight API Client Library

Use this client in your Ruby/Rails applications for ease of use access to the Client API.

Unlike typical ActiveResource clients, the Daylight API Client has been designed to be used similarly to ActiveRecord with scopes and the ability to chain queries.

ClientAPI::Post.all
ClientAPI::Post.where(code:'iad1')
ClientAPI::Post.published                  # scope
ClientAPI::Post.find(1).comments           # associations
ClientAPI::Post.find(1).public_commenters  # remote method on model
ClientAPI::Post.find(1).commenters.
  where(username: 'reidmix')               # chaining

Build your client models using Daylight::API, it is a wrapper with extended functionality to ActiveResource::Base

class ClientAPI::Post < Daylight::API
  scopes :internal

  belongs_to :user
  has_many   :comments
  has_many   :commenters, through: :comments

  remote :public_commenters, class_name: 'client_api/user'
end

Once all your client models are built, setup your API Client Library and startup via ‘setup!` (in an intitializer):

require 'client_api'

Daylight::API.setup!({
  namespace: 'client_api',
  password:  'test',
  endpoint:  'http://api.example.org/
})

Defined Under Namespace

Classes: HashResourcePassthrough

Constant Summary collapse

DEFAULT_CONFIG =
{
  namespace: 'API',
  endpoint:  'http://localhost',
  versions:  %w[v1]
}.freeze

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ReadOnly

#read_only, #respond_to?, #serializable_hash, #to_xml

Methods included from AssociationPersistance

#changed?, #serializable_hash

Constructor Details

#initialize(attributes = {}, persisted = false) ⇒ API

Extends ActiveResource to allow for saving metadata from the responses on the ‘meta` key. Will store this metadata on the `metadata` attribute.


Does this extension by overwritting ActiveResource::Base#initialize method Concern cannot call ‘super` from module to base class (we think)



199
200
201
202
203
204
205
206
# File 'lib/daylight/api.rb', line 199

def initialize(attributes={}, persisted = false)
  extract_metadata!(attributes)

  super

  @association_hashcodes = {}.with_indifferent_access
  @hashcode = self.attributes.hash
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Daylight::ReadOnly

Class Attribute Details

.namespaceObject

Returns the value of attribute namespace.



50
51
52
# File 'lib/daylight/api.rb', line 50

def namespace
  @namespace
end

.versionObject

Returns the value of attribute version.



50
51
52
# File 'lib/daylight/api.rb', line 50

def version
  @version
end

.versionsObject

Returns the value of attribute versions.



50
51
52
# File 'lib/daylight/api.rb', line 50

def versions
  @versions
end

Instance Attribute Details

#association_hashcodesObject (readonly)

Returns the value of attribute association_hashcodes.



190
191
192
# File 'lib/daylight/api.rb', line 190

def association_hashcodes
  @association_hashcodes
end

#hashcodeObject (readonly)

Returns the value of attribute hashcode.



190
191
192
# File 'lib/daylight/api.rb', line 190

def hashcode
  @hashcode
end

#metadataObject (readonly)

Returns the value of attribute metadata.



190
191
192
# File 'lib/daylight/api.rb', line 190

def 
  @metadata
end

Class Method Details

.find_single(scope, options) ⇒ Object

Find a single resource from the default URL

Fixes bug to short-circuit and return ‘nil` if scope/id is nil. ActiveResource::Base will perform the call and return with an error.



119
120
121
122
# File 'lib/daylight/api.rb', line 119

def find_single(scope, options)
  return if scope.nil?
  super
end

.request_root_in_json?Boolean

Whether to show root for the request

API requires JSON request to emit a root node named after the object’s type this is different from ‘include_root_in_json` where every `ActiveResource` supplies its root.

This causes problems with ‘accepts_nessted_attributes_for` where the *_attributes do not need it (and is broken by having a root elmenet)

Turned on by default when transmitting JSON requests.

See: encode

Returns:

  • (Boolean)


139
140
141
# File 'lib/daylight/api.rb', line 139

def request_root_in_json?
  request_root_in_json && format.extension == 'json'
end

.setup!(options = {}) ⇒ Object

Setup and configure the Daylight API. Must be called before Client API use. Will use the following defaults:

Daylight::API.setup!({
  namespace: 'API',
  password:  nil,
  endpoint:  'http://localhost',
  versions:  ['v1'],
  version:   'v1'
  timeout:   60  # in seconds
})

Daylight currenly requires that your API is within a module ‘namespace`

The ‘endpoint` sets ActiveResource#site configuration. The `password` is the HTTP Authentication password.

Daylight assumes you’re versioning your API, you can supply the ‘versions` that are supported by your API and which `version` is active.

By default, ActiveResource#request_root_in_json is set to true. You can turn this off with the ‘request_root_in_json` configuration.

A convenience for versioned APIs is to alias the active Client API models to versionless constance. For example

ClientAPI::V1::Post

Aliased to:

ClientAPI::Post

This functionalitity is turned on using the ‘alias_apis` configuration.



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/daylight/api.rb', line 95

def setup! options={}
  config = options.with_indifferent_access.reverse_merge(DEFAULT_CONFIG)

  self.namespace = config[:namespace]
  self.password  = config[:password]
  self.endpoint  = config[:endpoint]
  self.versions  = config[:versions].freeze
  self.version   = config[:version] || config[:versions].last  # specify or use most recent version
  self.timeout   = config[:timeout] if config[:timeout]        # default read_timeout is 60

  # Only "parent" elements required to emit a root node
  self.request_root_in_json = config[:request_root_in_json] || true

  headers['X-Daylight-Framework'] = Daylight::VERSION

  alias_apis unless config[:no_alias_apis]
end

Instance Method Details

#encode(options = {}) ⇒ Object

Returns the serialized string representation of the resource in the configured serialization format specified in ActiveResource::Base.format.

For JSON formatted requests default option is to include the root element depending on the ‘request_root_in_json` configuration.



253
254
255
# File 'lib/daylight/api.rb', line 253

def encode(options={})
  super(self.class.request_root_in_json? ? { :root => self.class.element_name }.merge(options) : options)
end

#find_or_create_resource_for(name) ⇒ Object

When an association is supplied via a hash of ‘*_attributes` then create (a set) of new Client API objects instead of leaving as a hash.



237
238
239
240
241
242
243
244
# File 'lib/daylight/api.rb', line 237

def find_or_create_resource_for name
  # if the key is attributes attributes for a configured association
  if /(?:_attributes)\z/ =~ name && reflections.key?($`.to_sym)
    HashResourcePassthrough
  else
    super
  end
end

#nested_resourcesObject

Get the list of nested_resources from the metadata attribute. If there are none then an empty array is supplied.

See: metadata



215
216
217
# File 'lib/daylight/api.rb', line 215

def nested_resources
  @nested_resources ||= [:nested_resources] || []
end