Class: Aptible::Resource::Base

Inherits:
HyperResource show all
Defined in:
lib/aptible/resource/base.rb

Overview

rubocop:disable ClassLength

Constant Summary

Constants inherited from HyperResource

HyperResource::VERSION, HyperResource::VERSION_DATE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from HyperResource

#[], #_hr_new_from_link, #_hr_response_class, #changed?, #deserialized_response, #each, #get_data_type_from_response, #incoming_body_filter, #inspect, #method_missing, namespaced_class, #outgoing_body_filter, #outgoing_uri_filter, #response_body, response_class, #response_object

Methods included from HyperResource::Modules::InternalAttributes

included

Methods included from HyperResource::Modules::HTTP

#create, #faraday_connection, #get, #patch, #post, #put

Constructor Details

#initialize(options = {}) ⇒ Base

rubocop:disable MethodLength



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/aptible/resource/base.rb', line 159

def initialize(options = {})
  if options.is_a?(Hash)
    self.token = options[:token]

    options[:root] ||= root_url
    options[:namespace] ||= namespace
    options[:headers] ||= {}
    options[:headers].merge!(
      'Content-Type' => 'application/json',
      'Authorization' => "Bearer #{bearer_token}"
    ) if options[:token]
  end

  super(options)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class HyperResource

Instance Attribute Details

#errorsObject

Returns the value of attribute errors.



19
20
21
# File 'lib/aptible/resource/base.rb', line 19

def errors
  @errors
end

#tokenObject

Returns the value of attribute token.



19
20
21
# File 'lib/aptible/resource/base.rb', line 19

def token
  @token
end

Class Method Details

.adapterObject



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

def self.adapter
  Aptible::Resource::Adapter
end

.all(options = {}) ⇒ Object



38
39
40
41
42
# File 'lib/aptible/resource/base.rb', line 38

def self.all(options = {})
  resource = find_by_url(collection_href, options)
  return [] unless resource
  resource.send(basename).entries
end

.basenameObject



34
35
36
# File 'lib/aptible/resource/base.rb', line 34

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

.belongs_to(relation) ⇒ Object



93
94
95
96
97
98
99
100
101
102
# File 'lib/aptible/resource/base.rb', line 93

def self.belongs_to(relation)
  define_method relation do
    get unless loaded
    if (memoized = instance_variable_get("@#{relation}"))
      memoized
    elsif links[relation]
      instance_variable_set("@#{relation}", links[relation].get)
    end
  end
end

.cast_field(value, type) ⇒ Object



148
149
150
151
152
153
154
155
156
# File 'lib/aptible/resource/base.rb', line 148

def self.cast_field(value, type)
  if type == Time
    Time.parse(value) if value
  elsif type == DateTime
    DateTime.parse(value) if value
  else
    value
  end
end

.collection_hrefObject



30
31
32
# File 'lib/aptible/resource/base.rb', line 30

def self.collection_href
  "/#{basename}"
end

.create(params = {}) ⇒ Object



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

def self.create(params = {})
  create!(params)
rescue HyperResource::ResponseError => e
  new.tap { |resource| resource.errors = Errors.from_exception(e) }
end

.create!(params = {}) ⇒ Object



65
66
67
68
69
# File 'lib/aptible/resource/base.rb', line 65

def self.create!(params = {})
  token = params.delete(:token)
  resource = new(token: token)
  resource.send(basename).create(normalize_params(params))
end

.define_has_many_getter(relation) ⇒ Object

rubocop:enable PredicateName



111
112
113
114
115
116
117
118
119
120
# File 'lib/aptible/resource/base.rb', line 111

def self.define_has_many_getter(relation)
  define_method relation do
    get unless loaded
    if (memoized = instance_variable_get("@#{relation}"))
      memoized
    elsif links[relation]
      instance_variable_set("@#{relation}", links[relation].entries)
    end
  end
end

.define_has_many_setter(relation) ⇒ Object

rubocop:disable MethodLength



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/aptible/resource/base.rb', line 123

def self.define_has_many_setter(relation)
  define_method "create_#{relation.to_s.singularize}!" do |params = {}|
    get unless loaded
    links[relation].create(self.class.normalize_params(params))
  end

  define_method "create_#{relation.to_s.singularize}" do |params = {}|
    begin
      send "create_#{relation.to_s.singularize}!", params
    rescue HyperResource::ResponseError => e
      Base.new(root: root_url, namespace: namespace).tap do |base|
        base.errors = Errors.from_exception(e)
      end
    end
  end
end

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

rubocop:enable PredicateName



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

def self.field(name, options = {})
  define_method name do
    self.class.cast_field(attributes[name], options[:type])
  end

  # Define ? accessor for Boolean attributes
  define_method("#{name}?") { !!send(name) } if options[:type] == Boolean
end

.find(id, options = {}) ⇒ Object



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

def self.find(id, options = {})
  find_by_url("#{collection_href}/#{id}", options)
end

.find_by_url(url, options = {}) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/aptible/resource/base.rb', line 54

def self.find_by_url(url, options = {})
  # REVIEW: Should exception be raised if return type mismatch?
  new(options).find_by_url(url)
rescue HyperResource::ClientError => e
  if e.response.status == 404
    return nil
  else
    raise e
  end
end

.get_data_type_from_response(response) ⇒ Object



21
22
23
24
# File 'lib/aptible/resource/base.rb', line 21

def self.get_data_type_from_response(response)
  return nil unless response && response.body
  adapter.get_data_type_from_object(adapter.deserialize(response.body))
end

.has_many(relation) ⇒ Object

rubocop:disable PredicateName



78
79
80
81
# File 'lib/aptible/resource/base.rb', line 78

def self.has_many(relation)
  define_has_many_getter(relation)
  define_has_many_setter(relation)
end

.has_one(relation) ⇒ Object

rubocop:disable PredicateName



105
106
107
108
# File 'lib/aptible/resource/base.rb', line 105

def self.has_one(relation)
  # Better than class << self + alias_method?
  belongs_to(relation)
end

.normalize_params(params = {}) ⇒ Object

rubocop:enable MethodLength



141
142
143
144
145
146
# File 'lib/aptible/resource/base.rb', line 141

def self.normalize_params(params = {})
  params_array = params.map do |key, value|
    value.is_a?(HyperResource) ? [key, value.href] : [key, value]
  end
  Hash[params_array]
end

.where(options = {}) ⇒ Object



44
45
46
47
48
# File 'lib/aptible/resource/base.rb', line 44

def self.where(options = {})
  params = options.except(:token, :root, :namespace, :headers)
  params = normalize_params(params)
  find_by_url("#{collection_href}?#{params.to_query}", options).entries
end

Instance Method Details

#_hyperresource_updateObject



202
# File 'lib/aptible/resource/base.rb', line 202

alias_method :_hyperresource_update, :update

#adapterObject

rubocop:enable MethodLength



176
177
178
# File 'lib/aptible/resource/base.rb', line 176

def adapter
  self.class.adapter
end

#bearer_tokenObject



194
195
196
197
198
199
200
# File 'lib/aptible/resource/base.rb', line 194

def bearer_token
  case token
  when Aptible::Resource::Base then token.access_token
  when Fridge::AccessToken then token.to_s
  when String then token
  end
end

#deleteObject Also known as: destroy



216
217
218
219
220
221
# File 'lib/aptible/resource/base.rb', line 216

def delete
  super
rescue HyperResource::ResponseError
  # HyperResource/Faraday choke on empty response bodies
  nil
end

#error_htmlObject



233
234
235
# File 'lib/aptible/resource/base.rb', line 233

def error_html
  errors.full_messages.join('<br />')
end

#find_by_url(url_or_href) ⇒ Object



188
189
190
191
192
# File 'lib/aptible/resource/base.rb', line 188

def find_by_url(url_or_href)
  resource = dup
  resource.href = url_or_href.gsub(/^#{root}/, '')
  resource.get
end

#namespaceObject



180
181
182
# File 'lib/aptible/resource/base.rb', line 180

def namespace
  fail 'Resource server namespace must be defined by subclass'
end

#reloadObject

NOTE: The following does not update the object in-place



225
226
227
# File 'lib/aptible/resource/base.rb', line 225

def reload
  self.class.find_by_url(href, headers: headers)
end

#root_urlObject



184
185
186
# File 'lib/aptible/resource/base.rb', line 184

def root_url
  fail 'Resource server root URL must be defined by subclass'
end

#update(params) ⇒ Object



210
211
212
213
214
# File 'lib/aptible/resource/base.rb', line 210

def update(params)
  update!(params)
rescue HyperResource::ResponseError
  false
end

#update!(params) ⇒ Object



203
204
205
206
207
208
# File 'lib/aptible/resource/base.rb', line 203

def update!(params)
  _hyperresource_update(self.class.normalize_params(params))
rescue HyperResource::ResponseError => e
  self.errors = Errors.from_exception(e)
  raise e
end