class TinyClient::Resource

This is the core of TinyClient. Subclass {TinyClient::Resource} in order to create an HTTP/JSON tiny client.

{file:README.md Getting Started} @author @barjo

Attributes

changes[R]

the fields that has beem modified, and will be save on {save!}

id[RW]

A resource always have an id

Public Class Methods

build(hash, track_changes = true) click to toggle source

Create a resouce instance from an Hash. @param [Hash] hash the resource fields with their values @param [Boolean] track_changes if true all fields will be marked has changed @return [Resource] the newly created resource

# File lib/tiny_client/resource.rb, line 107
def build(hash, track_changes = true)
  resource = fields.each_with_object(new) do |field, r|
    value = hash.fetch(field.to_s, hash[field.to_sym])
    r.send("#{field}=", value)
  end
  resource.clear_changes! unless track_changes
  resource
end
conf(config) click to toggle source

Set this resource client configuration @param [Configuration] config the api url and client default headers.

# File lib/tiny_client/resource.rb, line 18
def conf(config)
  @conf ||= config
end
create(content) click to toggle source

POST /<resource_path>.json Create a new resource. The resource will be indexed by it's name. @param [Object] content the resource/attributes to be created. @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return the created resource

# File lib/tiny_client/resource.rb, line 46
def create(content)
  data = { low_name => content }
  post(data)
end
delete(id = nil, name = nil, resource_class = nil) click to toggle source

delete /<path>/{id}.json @raise [ResponseError] if the server respond with an error status (i.e 404, 500..)

# File lib/tiny_client/resource.rb, line 94
def delete(id = nil, name = nil, resource_class = nil)
  resp = @conf.requestor.delete(@path, id, name)
  (resource_class || self).from_response resp
end
fields(*names) click to toggle source

@param [*String] names the resource field names

# File lib/tiny_client/resource.rb, line 29
def fields(*names)
  @fields ||= field_accessor(names) && names
end
get(params = {}, id = nil, name = nil, resource_class = nil) click to toggle source

GET /<path>/{id}/<name> @raise [ResponseError] if the server respond with an error status (i.e 404, 500..)

# File lib/tiny_client/resource.rb, line 61
def get(params = {}, id = nil, name = nil, resource_class = nil)
  resp = @conf.requestor.get(@path, params, id, name)
  (resource_class || self).from_response resp
end
index(params = {}) click to toggle source

GET /<path>.json @param [Hash] params query parameters @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return [Enumerator] enumerate the resources available at this path.

# File lib/tiny_client/resource.rb, line 37
def index(params = {})
  get(params)
end
last_response() click to toggle source

@return [Response] the last response that has been received for that resource

# File lib/tiny_client/resource.rb, line 117
def last_response
  Thread.current[:_tclr]
end
low_name() click to toggle source
# File lib/tiny_client/resource.rb, line 99
def low_name
  @low_name ||= name.demodulize.underscore
end
new(*_args) click to toggle source
# File lib/tiny_client/resource.rb, line 163
def initialize(*_args)
  @id = nil
  @changes = Set.new # store the fields change here
end
path(path = nil) click to toggle source

Set the resource path, default is the class name in lower case. @param [String] path the resource path

# File lib/tiny_client/resource.rb, line 24
def path(path = nil)
  @path ||= path || low_name
end
post(data, id = nil, name = nil, resource_class = nil) click to toggle source

POST /<path>/{id}/<name> @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @raise [ArgumentError] if data cannot be serialized as a json string ( .to_json )

# File lib/tiny_client/resource.rb, line 69
def post(data, id = nil, name = nil, resource_class = nil)
  resp = @conf.requestor.post(data, @path, id, name)
  (resource_class || self).from_response resp
end
put(data, id = nil, name = nil, resource_class = nil) click to toggle source

PUT /<path>/{id}/<name> @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @raise [ArgumentError] if data cannot be serialized as a json string ( .to_json )

# File lib/tiny_client/resource.rb, line 87
def put(data, id = nil, name = nil, resource_class = nil)
  resp = @conf.requestor.put(data, @path, id, name)
  (resource_class || self).from_response resp
end
show(id, params = {}) click to toggle source

GET /<resource_path>/{id} @param [String, Integer] id the resource id @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return the resource available at that path

# File lib/tiny_client/resource.rb, line 55
def show(id, params = {})
  get(params, id)
end
update(id, content) click to toggle source

Will query PUT /<path>/{id} @param [String, Integer] id the id of the resource that needs to be updated @param [Object] content the updated attributes/fields/resource @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return the updated resource

# File lib/tiny_client/resource.rb, line 79
def update(id, content)
  data = { low_name => content }
  put(data, id)
end

Protected Class Methods

from_response(response) click to toggle source

Create a resource instance from a {Response}. If the response contains an Array of resource hash, an Enumerator will be return. @param [Response] response obtained from making a request. @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return [Resource, Enumerator, nil] the resources created from the given response.

# File lib/tiny_client/resource.rb, line 128
def from_response(response)
  Thread.current[:_tclr] = response
  case body = response.parse_body
  when Hash
    build(body, false)
  when Array
    Enumerator.new(body.size) do |yielder|
      inner = body.each
      loop { yielder << build(inner.next, false) }
    end
  end
end

Private Class Methods

field_accessor(names) click to toggle source
# File lib/tiny_client/resource.rb, line 143
      def field_accessor(names)
        names.each do |name|
          class_eval <<-RUBY
            def #{name}; @#{name} end

            def #{name}=(#{name})
              @#{name}= #{name}
              @changes << :#{name} # keep track of fields that has been modified
            end
            RUBY
        end
      end

Public Instance Methods

as_json(options = {}) click to toggle source

see edgeguides.rubyonrails.org/active_support_core_extensions.html#json-support @param [Hash] options for the hash transformation @option [Array] only limit the hash content to those fields @return [Hash] a json ready representation of this resource

# File lib/tiny_client/resource.rb, line 219
def as_json(options = {})
  self.class.fields.each_with_object({}) do |field, h|
    h[field] = send(field)
  end.as_json(options)
end
Also aliased as: to_h
clear_changes!() click to toggle source

Mark all fields has not changed. This mean that calling save! will not modify this resource until a field attribute has been changed.

# File lib/tiny_client/resource.rb, line 211
def clear_changes!
  @changes.clear
end
destroy!() click to toggle source

Destroy this resource. It will call delete on this resource id. DELETE /path/id @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @raise [ResourceError] if this resource does not have an id. @return the deleted resource

# File lib/tiny_client/resource.rb, line 187
def destroy!
  raise ResourceError, 'Cannot delete resource if @id not present' if id.blank?
  self.class.delete(id)
  self
end
load!(params = {}) click to toggle source

Load/Reload this resource from the server. It will reset all fields that has been retrieved through the request. It will do a GET request on the resource id (:show) @param [Hash] params optional query parameters @raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @raise [ResourceError] if this resource does not have an id. @return self with updated fields.

# File lib/tiny_client/resource.rb, line 200
def load!(params = {})
  raise ResourceError, 'Cannot load resource if @id not present' if id.blank?
  # get the values from the persistence layer
  reloaded = self.class.show(@id, params)
  clone_fields(reloaded)
  clear_changes!
  reloaded
end
save!() click to toggle source

Save the resource fields that has changed, or create it, if it's a new one!

Create the a new resource if id is not set or update the corresonding resource.
Create is done by calling POST on the resource path
Update is done by calling PUT on the resource id ( path/id )

@raise [ResponseError] if the server respond with an error status (i.e 404, 500..) @return [Resource] the updated resource

# File lib/tiny_client/resource.rb, line 174
def save!
  data = @changes.to_a.each_with_object({}) { |field, h| h[field] = send(field) }
  saved = id.present? ? self.class.update(id, data) : self.class.create(data)
  clone_fields(saved)
  clear_changes!
  self
end
to_h(options = {})
Alias for: as_json

Private Instance Methods

clone_fields(resource) click to toggle source
# File lib/tiny_client/resource.rb, line 229
def clone_fields(resource)
  self.class.fields.each { |f| send("#{f}=", resource.send(f)) }
end