Class: Alula::ApiResource

Inherits:
Object
  • Object
show all
Defined in:
lib/alula/api_resource.rb

Overview

Parent class for all API objects

Defined Under Namespace

Classes: ModelErrors

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id = nil, attributes = {}) ⇒ ApiResource

Returns a new instance of ApiResource.



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/alula/api_resource.rb', line 10

def initialize(id = nil, attributes = {})
  @raw_data = {}
  @values = {}
  @dirty_attributes = Set.new
  @errors = ModelErrors.new(self.class)

  construct_from(
    'id' => id,
    'attributes' => attributes
  )
end

Instance Attribute Details

#dirty_attributesObject

Returns the value of attribute dirty_attributes.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def dirty_attributes
  @dirty_attributes
end

#errorsObject

Returns the value of attribute errors.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def errors
  @errors
end

#idObject

Returns the value of attribute id.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def id
  @id
end

Returns the value of attribute link_matchers.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def link_matchers
  @link_matchers
end

Returns the value of attribute links.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def links
  @links
end

#rate_limitObject

Returns the value of attribute rate_limit.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def rate_limit
  @rate_limit
end

#raw_dataObject

Returns the value of attribute raw_data.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def raw_data
  @raw_data
end

#valuesObject

Returns the value of attribute values.



4
5
6
# File 'lib/alula/api_resource.rb', line 4

def values
  @values
end

Class Method Details

.buildObject

Construct a new resource, ready to receive attributes, with empty values for all attrs. Useful for making New resources TODO: This will need testing and probably more work when we

actually use it, at the moment we're only retrieving and
modifying existing models.


33
34
35
36
37
# File 'lib/alula/api_resource.rb', line 33

def self.build
  fields = self.get_fields.keys.map{ |k| Util.camelize(k) }
  empty_shell = fields.each_with_object({}) { |f, obj| obj[f] = nil }
  self.new(nil, empty_shell)
end

.class_nameObject



6
7
8
# File 'lib/alula/api_resource.rb', line 6

def self.class_name
  name.split("::")[-1]
end

Instance Method Details

#annotate_errors(model_errors) ⇒ Object



124
125
126
127
128
129
# File 'lib/alula/api_resource.rb', line 124

def annotate_errors(model_errors)
  @errors = ModelErrors.new(self.class)
  model_errors.each_pair do |field_name, error|
    errors.add(field_name, error)
  end
end

#apply_attributes(attributes) ⇒ Object

Take a hash of attributes and apply them to the model



56
57
58
59
60
# File 'lib/alula/api_resource.rb', line 56

def apply_attributes(attributes)
  attributes.each do |key, value|
    self.send("#{key}=", value)
  end
end

#as_jsonObject

Fetch known attributes out of the object, collected into a Hash in camelCase format Intended for eventually making its way back up to the API



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/alula/api_resource.rb', line 91

def as_json
  self.field_names.each_with_object({}) do |ruby_key, obj|
    key      = Util.camelize(ruby_key)
    val = self.send(ruby_key)

    if self.date_fields.include?(ruby_key) && ![nil, ''].include?(val)
      if val.respond_to? :strftime
        obj[key] = val.strftime('%Y-%m-%dT%H:%M:%S.%L%z')
      else
        obj[key] = val.to_s
      end
    elsif val.is_a? Alula::ObjectField
      obj[key] = val.as_json
    else
      obj[key] = val
    end
  end
end

#as_patchable_jsonObject

Reduce as_json to a set that can be updated, removing any fields that are not patchable by the user



113
114
115
116
117
118
119
120
121
122
# File 'lib/alula/api_resource.rb', line 113

def as_patchable_json
  values = as_json.each_pair.each_with_object({}) do |(key, value), collector|
    ruby_key = Util.underscore(key).to_sym
    collector[key] = value if !read_only_attributes.include?(ruby_key) && dirty?(ruby_key)
  end

  # Remove blank values if creating a new record
  values = values.select{ |k, v| !v.nil? } unless persisted?
  values
end

Links are hashes that identify any included models, they are used to distribute included models when also including relationships See list.rb#build_and_merge_relationships for details on usage



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/alula/api_resource.rb', line 135

def cache_links(links)
  @links = links

  @link_matchers = links.each_pair.each_with_object([]) do |(type, link), collection|
    data = link['data']
    next if data.nil?

    if data.is_a?(Array)
      data.each do |nested_link|
        collection << { type: nested_link['type'], id: nested_link['id'] }.freeze
      end
    else
      collection << { type: data['type'], id: data['id'] }.freeze
    end
  end
end

#cloneObject



22
23
24
# File 'lib/alula/api_resource.rb', line 22

def clone
  self.class.new(nil, @raw_data['attributes'])
end

#construct_from(json_object) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/alula/api_resource.rb', line 39

def construct_from(json_object)
  @raw_data = json_object.dup
  @values = json_object['attributes']

  self.id = json_object['id'] unless [nil, ''].include?(json_object['id'])

  @dirty_attributes = Set.new
  @errors = ModelErrors.new(self.class)

  @related_models = {}
  cache_links(json_object['relationships'] || {})

  self
end

#dirty?(attribute_name = nil) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
# File 'lib/alula/api_resource.rb', line 66

def dirty?(attribute_name = nil)
  return @dirty_attributes.any? if attribute_name.nil?

  @dirty_attributes.include? attribute_name.to_sym
end

#errors?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/alula/api_resource.rb', line 72

def errors?
  @errors.any?
end

#filter_builderObject Also known as: fb

Return an instance of QueryEngine annotated with the correct model attributes



154
155
156
# File 'lib/alula/api_resource.rb', line 154

def filter_builder
  Alula::FilterBuilder.new(self.class)
end

#model_nameObject



159
160
161
# File 'lib/alula/api_resource.rb', line 159

def model_name
  self.class
end

#reconstruct_from(json_object) ⇒ Object



62
63
64
# File 'lib/alula/api_resource.rb', line 62

def reconstruct_from(json_object)
  construct_from(json_object)
end

#refreshObject



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/alula/api_resource.rb', line 76

def refresh
  response = Alula::Client.request(:get, resource_url, {}, {})
  if response.ok?
    model = construct_from(response.data['data'])
    model.rate_limit = response.rate_limit
    model
  else
    error_class = AlulaError.for_response(response)
    raise error_class
  end
end