Class: TinyClient::Resource

Inherits:
Object
  • Object
show all
Includes:
NestedSupport, PaginationSupport
Defined in:
lib/tiny_client/resource.rb

Overview

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

Getting Started

Author:

  • @barjo

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NestedSupport

included, #nested_all, #nested_create, #nested_delete, #nested_index, #nested_show, #nested_update

Methods included from PaginationSupport

included

Constructor Details

#initialize(*_args) ⇒ Resource

Returns a new instance of Resource



166
167
168
# File 'lib/tiny_client/resource.rb', line 166

def initialize(*_args)
  @changes = Set.new # store the fields change here
end

Instance Attribute Details

#changesObject (readonly)

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



164
165
166
# File 'lib/tiny_client/resource.rb', line 164

def changes
  @changes
end

#idObject

A resource always have an id



15
16
17
# File 'lib/tiny_client/resource.rb', line 15

def id
  @id
end

Class Method Details

.build(hash, track_changes = true) ⇒ Resource

Create a resouce instance from an Hash.

Parameters:

  • hash (Hash)

    the resource fields with their values

  • track_changes (Boolean) (defaults to: true)

    if true all fields will be marked has changed

Returns:

  • (Resource)

    the newly created resource



111
112
113
114
115
116
117
118
# File 'lib/tiny_client/resource.rb', line 111

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) ⇒ Object

Set this resource client configuration

Parameters:

  • config (Configuration)

    the api url and client default headers.



20
21
22
# File 'lib/tiny_client/resource.rb', line 20

def conf(config)
  @conf ||= config
end

.create(content) ⇒ Object

POST /<resource_path>.json Create a new resource. The resource will be indexed by it's name.

Parameters:

  • content (Object)

    the resource/attributes to be created.

Returns:

  • the created resource

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



48
49
50
51
# File 'lib/tiny_client/resource.rb', line 48

def create(content)
  data = { low_name => content }
  post(data)
end

.delete(id = nil, name = nil, resource_class = nil) ⇒ Object

delete /<path>/#id.json

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



98
99
100
101
# File 'lib/tiny_client/resource.rb', line 98

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) ⇒ Object

Parameters:

  • names (*String)

    the resource field names



31
32
33
# File 'lib/tiny_client/resource.rb', line 31

def fields(*names)
  @fields ||= field_accessor(names) && names
end

.get(params = {}, id = nil, name = nil, resource_class = nil) ⇒ Object

GET /<path>/#id/<name>

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



63
64
65
66
# File 'lib/tiny_client/resource.rb', line 63

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 = {}) ⇒ Enumerator

GET /<path>.json

Parameters:

  • params (Hash) (defaults to: {})

    query parameters

Returns:

  • (Enumerator)

    enumerate the resources available at this path.

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



39
40
41
# File 'lib/tiny_client/resource.rb', line 39

def index(params = {})
  get(params)
end

.last_responseResponse

Returns the last response that has been received for that resource

Returns:

  • (Response)

    the last response that has been received for that resource



121
122
123
# File 'lib/tiny_client/resource.rb', line 121

def last_response
  Thread.current[:_tclr]
end

.low_nameObject



103
104
105
# File 'lib/tiny_client/resource.rb', line 103

def low_name
  @low_name ||= name.demodulize.downcase
end

.path(path = nil) ⇒ Object

Set the resource path, default is the class name in lower case.

Parameters:

  • path (String) (defaults to: nil)

    the resource path



26
27
28
# File 'lib/tiny_client/resource.rb', line 26

def path(path = nil)
  @path ||= path || low_name
end

.post(data, id = nil, name = nil, resource_class = nil) ⇒ Object

POST /<path>/#id/<name>

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)

  • (ArgumentError)

    if data cannot be serialized as a json string ( .to_json )



71
72
73
74
75
# File 'lib/tiny_client/resource.rb', line 71

def post(data, id = nil, name = nil, resource_class = nil)
  verify_json(data)
  resp = @conf.requestor.post(data, @path, id, name)
  (resource_class || self).from_response resp
end

.put(data, id = nil, name = nil, resource_class = nil) ⇒ Object

PUT /<path>/#id/<name>

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)

  • (ArgumentError)

    if data cannot be serialized as a json string ( .to_json )



90
91
92
93
94
# File 'lib/tiny_client/resource.rb', line 90

def put(data, id = nil, name = nil, resource_class = nil)
  verify_json(data)
  resp = @conf.requestor.put(data, @path, id, name)
  (resource_class || self).from_response resp
end

.show(id, params = {}) ⇒ Object

GET /<resource_path>/#id

Parameters:

  • id (String, Integer)

    the resource id

Returns:

  • the resource available at that path

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



57
58
59
# File 'lib/tiny_client/resource.rb', line 57

def show(id, params = {})
  get(params, id)
end

.update(id, content) ⇒ Object

Will query PUT /<path>/#id

Parameters:

  • id (String, Integer)

    the id of the resource that needs to be updated

  • content (Object)

    the updated attributes/fields/resource

Returns:

  • the updated resource

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



82
83
84
85
# File 'lib/tiny_client/resource.rb', line 82

def update(id, content)
  data = { low_name => content }
  put(data, id)
end

Instance Method Details

#as_json(options = {}) ⇒ Hash Also known as: to_h

Parameters:

  • options (Hash) (defaults to: {})

    for the hash transformation

  • [Array] (Hash)

    a customizable set of options

Returns:

  • (Hash)

    a json ready representation of this resource



221
222
223
224
225
# File 'lib/tiny_client/resource.rb', line 221

def as_json(options = {})
  self.class.fields.each_with_object({}) do |field, h|
    h[field] = send(field)
  end.as_json(options)
end

#clear_changes!Object

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



213
214
215
# File 'lib/tiny_client/resource.rb', line 213

def clear_changes!
  @changes.clear
end

#destroy!Object

Destroy this resource. It will call delete on this resource id. DELETE /path/id

Returns:

  • the deleted resource

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)

  • (ResourceError)

    if this resource does not have an id.



189
190
191
192
193
# File 'lib/tiny_client/resource.rb', line 189

def destroy!
  raise ResourceError, 'Cannot delete resource if @id not present' if id.blank?
  self.class.delete(id)
  self
end

#load!(params = {}) ⇒ Object

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)

Parameters:

  • params (Hash) (defaults to: {})

    optional query parameters

Returns:

  • self with updated fields.

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)

  • (ResourceError)

    if this resource does not have an id.



202
203
204
205
206
207
208
209
# File 'lib/tiny_client/resource.rb', line 202

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!Resource

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 )

Returns:

Raises:

  • (ResponseError)

    if the server respond with an error status (i.e 404, 500..)



176
177
178
179
180
181
182
# File 'lib/tiny_client/resource.rb', line 176

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