Class: Vend::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/vend/base.rb

Overview

This Base class provides the basic mapping between Vend::Resource subclasses and the HTTP endpoints in the Vend API.

Not all CRUD actions are available for every resource, and at current there is no PUT endpoint and hence no update action

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, options = {}) ⇒ Base

:nodoc:



16
17
18
19
# File 'lib/vend/base.rb', line 16

def initialize(client, options = {}) #:nodoc:
  @client = client
  @attrs = options[:attrs] || {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *_args, &_block) ⇒ Object

Overrides method_missing to query the attrs hash for the value stored at the specified key before proxying it to the object



171
172
173
174
175
176
177
# File 'lib/vend/base.rb', line 171

def method_missing(method_name, *_args, &_block)
  if attrs.keys.include? method_name.to_s
    attribute_value_for(method_name)
  else
    super(method_name)
  end
end

Instance Attribute Details

#attrsObject

Hash of attributes for this instance. Represents the data returned from the Vend API



14
15
16
# File 'lib/vend/base.rb', line 14

def attrs
  @attrs
end

#clientObject (readonly)

Reference to the Vend::Client client object providing the HTTP interface to the API



10
11
12
# File 'lib/vend/base.rb', line 10

def client
  @client
end

Class Method Details

.accepts_scope?(scope_name) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/vend/base.rb', line 64

def self.accepts_scope?(scope_name)
  available_scopes.include?(scope_name)
end

.all(client) ⇒ Object

Returns a collection containing all of the specified resource objects. Will paginate.



50
51
52
# File 'lib/vend/base.rb', line 50

def self.all(client)
  initialize_collection(client, collection_name)
end

.attribute_castsObject



25
26
27
# File 'lib/vend/base.rb', line 25

def self.attribute_casts
  @attribute_casts ||= {}
end

.available_scopesObject

Returns the list of URL parameter scopes that are available for this resource. For example, if the resource accepted URLs like:

/api/resources/since/YYYY-MM-DD HH:MM:SS/outlet_id/abc-1234-def

this method would return [:since, :outlet_id]



60
61
62
# File 'lib/vend/base.rb', line 60

def self.available_scopes
  @available_scopes ||= []
end

.build(client, attrs) ⇒ Object

Builds a new instance of the described resource using the specified attributes.



112
113
114
# File 'lib/vend/base.rb', line 112

def self.build(client, attrs)
  self.new(client, attrs: attrs)
end

.build_from_json(client, json) ⇒ Object

Builds a collection of instances from a JSON response



117
118
119
120
121
# File 'lib/vend/base.rb', line 117

def self.build_from_json(client, json)
  json[collection_name].map do |attrs|
    self.build(client, attrs)
  end
end

.cast_attribute(attribute_name, type) ⇒ Object



21
22
23
# File 'lib/vend/base.rb', line 21

def self.cast_attribute(attribute_name, type)
  attribute_casts[attribute_name] = type
end

.collection_nameObject

Returns the endpoint name for a collection of this resource



36
37
38
# File 'lib/vend/base.rb', line 36

def self.collection_name
  endpoint_name.pluralize
end

.default_collection_request_argsObject

Override this with arguments that are required on every collection request. I.e, to default to 500 items per page:

def default_collection_request_args
  super.merge(url_params: {page_size: 500})
end


155
156
157
# File 'lib/vend/base.rb', line 155

def self.default_collection_request_args
  {}
end

.endpoint_nameObject

Returns the endpoint name for the resource, used in API urls when making requests.



31
32
33
# File 'lib/vend/base.rb', line 31

def self.endpoint_name
  self.name.split('::').last.underscore
end

.find(client, id) ⇒ Object

Attempts to pull a singular object from Vend through the singular GET endpoint.



136
137
138
139
# File 'lib/vend/base.rb', line 136

def self.find(client, id)
  response = client.request(singular_name(id))
  initialize_singular(client, response)
end

.findable_by(field, options = {}) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/vend/base.rb', line 93

def self.findable_by(field, options = {})
  (class << self; self; end).instance_eval do
    define_method("find_by_#{field}") do |client, *args|
      search(client, options[:as] || field, *args)
    end
  end
end

.initialize_collection(client, endpoint, args = {}) ⇒ Object

Will initialize a collection of Resources from the APIs JSON Response.



130
131
132
# File 'lib/vend/base.rb', line 130

def self.initialize_collection(client, endpoint, args = {})
  ResourceCollection.new(client, self, endpoint, args)
end

.initialize_singular(client, json) ⇒ Object

Initializes a single object from a JSON response. Assumes the response is a JSON array with a single item.



125
126
127
# File 'lib/vend/base.rb', line 125

def self.initialize_singular(client, json)
  self.build(client, json[collection_name].first)
end

.paginates?Boolean

Whether or not this resource can be paginated, false by default. Override this method in specific classes to enable pagination for that resource.

Returns:

  • (Boolean)


144
145
146
# File 'lib/vend/base.rb', line 144

def self.paginates?
  false
end

.search(client, field, query) ⇒ Object

Sends a search request to the API and initializes a collection of Resources from the response. This method is only used internally by find_by_field methods.



104
105
106
107
108
# File 'lib/vend/base.rb', line 104

def self.search(client, field, query)
  initialize_collection(
    client, collection_name,  url_params: { field.to_sym => query }
  )
end

.singular_name(id) ⇒ Object



44
45
46
# File 'lib/vend/base.rb', line 44

def self.singular_name(id)
  "#{collection_name}/#{id}"
end

.url_scope(method_name) ⇒ Object

Creates a class method that allows access to a filtered collection of resources on the API. For example:

class MyResource << Vend::Base
  url_scope :since
end

Will create a class method:

client.MyResource.since(argument)

That will call the following URL on the Vend API:

/api/my_resources/since/:argument

And return the corresponding collection of resources



84
85
86
87
88
89
90
91
# File 'lib/vend/base.rb', line 84

def self.url_scope(method_name)
  (class << self; self; end).instance_eval do
    define_method(method_name) do |client, arg|
      initialize_collection(client, collection_name).scope(method_name, arg)
    end
  end
  available_scopes << method_name
end

Instance Method Details

#deleteObject

Attempts to delete the resource. If an exception is thrown by delete!, it is caught and false is returned (typically when the resource is not a type which can be deleted).



182
183
184
185
186
# File 'lib/vend/base.rb', line 182

def delete
  delete!
rescue Vend::Resource::IllegalAction
  false
end

#delete!Object

Attempts to delete there resource. Will throw an exception when the attempt fails, otherwise will return true.



190
191
192
193
194
195
# File 'lib/vend/base.rb', line 190

def delete!
  raise(Vend::Resource::IllegalAction,
        "#{self.class.name} has no unique ID") unless attrs['id']
  client.request(singular_name, method: :delete)
  true
end

#respond_to?(method_name) ⇒ Boolean

Overrides respond_to? to query the attrs hash for the key before proxying it to the object

Returns:

  • (Boolean)


161
162
163
164
165
166
167
# File 'lib/vend/base.rb', line 161

def respond_to?(method_name)
  if attrs.keys.include? method_name.to_s
    true
  else
    super(method_name)
  end
end

#singular_nameObject



40
41
42
# File 'lib/vend/base.rb', line 40

def singular_name
  self.class.singular_name(id)
end