Class: Alula::DcpResource

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

Overview

Parent class for all DCP objects

Direct Known Subclasses

Alula::Dcp::BaseResource

Defined Under Namespace

Classes: ModelErrors

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(device_id, attributes = {}) ⇒ DcpResource

Returns a new instance of DcpResource.



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/alula/dcp_resource.rb', line 12

def initialize(device_id, attributes = {})
  @raw_data = {}
  @dirty_attributes = Set.new
  @values = attributes
  @errors = ModelErrors.new(self.class)
  klass = get_discriminated_class(attributes)
  if klass != self.class
    klass.new(device_id, attributes)
  else
    construct_from(device_id, attributes)
  end
end

Instance Attribute Details

#device_idObject

Returns the value of attribute device_id.



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

def device_id
  @device_id
end

#dirty_attributesObject

Returns the value of attribute dirty_attributes.



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

def dirty_attributes
  @dirty_attributes
end

#errorsObject

Returns the value of attribute errors.



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

def errors
  @errors
end

#metaObject

Returns the value of attribute meta.



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

def meta
  @meta
end

#rate_limitObject

Returns the value of attribute rate_limit.



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

def rate_limit
  @rate_limit
end

#raw_dataObject

Returns the value of attribute raw_data.



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

def raw_data
  @raw_data
end

#valuesObject

Returns the value of attribute values.



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

def values
  @values
end

Class Method Details

.build(device_id) ⇒ Object

Construct a new resource, ready to receive attributes, with empty values for all attrs. Useful for making New resources



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

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

.class_nameObject



8
9
10
# File 'lib/alula/dcp_resource.rb', line 8

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

.discriminate_by(mapping = nil) ⇒ Object



192
193
194
195
196
# File 'lib/alula/dcp_resource.rb', line 192

def discriminate_by(mapping = nil)
  return @discriminator_mapping unless mapping

  @discriminator_mapping = mapping
end

.discriminator(field_name = nil) ⇒ Object



186
187
188
189
190
# File 'lib/alula/dcp_resource.rb', line 186

def discriminator(field_name = nil)
  return @discriminator unless field_name

  @discriminator = field_name
end

Instance Method Details

#annotate_errors(model_errors) ⇒ Object



167
168
169
170
171
172
# File 'lib/alula/dcp_resource.rb', line 167

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, merge_only: false) ⇒ Object

Take a hash of attributes and apply them to the model



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/alula/dcp_resource.rb', line 52

def apply_attributes(attributes, merge_only: false)
  res = attributes.each do |key, value|
    json_key = Util.camelize(key.to_s)
    sym_key = key.to_sym
    opts = self.class.get_fields[sym_key] || self.class.get_fields[:primitive]
    if merge_only
      # merge the value into the existing value
      if value.is_a?(Array)
        value.each_index do |index|
          send(sym_key)[index].apply_attributes(value[index], merge_only: true)
        end
      elsif value.is_a?(Hash) && send(sym_key).respond_to?(:apply_attributes)
        send(sym_key).apply_attributes(value, merge_only: true)
      elsif value.is_a?(Hash) && send(sym_key).respond_to?(:each)
        send("#{key}=", value)
      elsif opts[:type] == :number
        @values[json_key] = value.to_i
      elsif opts[:type] == :boolean
        @values[json_key] = [true, 'true', 1, '1'].include?(value)
      else
        @values[json_key] = value
      end
    elsif self.class.has_svm
      send(:staged).send("#{key}=", value) if send(:staged).respond_to?(key)
    else
      send("#{key}=", value)
    end
  end
  return @values if merge_only

  res
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



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/alula/dcp_resource.rb', line 108

def as_json
  field_names.each_with_object({}) do |ruby_key, obj|
    key = Util.camelize(ruby_key)
    val = find_value(ruby_key)
    # we don't want to include nil values in the JSON (for now?)
    next if val.nil?

    # if the key is primitive and the class has svm, use staged as key
    if key == 'primitive' && self.class.has_svm
      key = 'staged'
    elsif self.class.has_svm && key != 'index'
      # if has_svm and not primitive field need to nest values inside 'staged' or 'value'
      # index is a special case, it's outside of staged/value
      obj['staged'] ||= {}
      obj['staged'][key] = pick_value_for_key(val, ruby_key)
      next
    end

    obj[key] = pick_value_for_key(val, ruby_key)
  end
end

#as_patchable_jsonObject

Reduce as_json to a set that can be updated



160
161
162
163
164
165
# File 'lib/alula/dcp_resource.rb', line 160

def as_patchable_json
  values = as_json.each_pair.each_with_object({}) do |(key, val), collector|
    collector[key] = val
  end
  values.reject { |k, _v| %w[index version].include? k } # blacklist index and version
end

#cloneObject



25
26
27
# File 'lib/alula/dcp_resource.rb', line 25

def clone
  self.class.new(@device_id, @raw_data)
end

#construct_from(device_id, json_object) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/alula/dcp_resource.rb', line 39

def construct_from(device_id, json_object)
  @raw_data = json_object.dup
  @values = json_object
  @meta = Alula::Dcp::Meta.new(@values['meta']) unless empty_value?(@values['meta'])
  self.device_id = device_id

  @errors = ModelErrors.new(self.class)

  self
end

#errors?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/alula/dcp_resource.rb', line 89

def errors?
  @errors.any?
end

#filter_builderObject Also known as: fb

Return an instance of QueryEngine annotated with the correct model attributes



176
177
178
# File 'lib/alula/dcp_resource.rb', line 176

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

#find_value(key) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/alula/dcp_resource.rb', line 140

def find_value(key)
  # index is a special case, it's not in staged or value
  # must return early to avoid errors when staged/value are primitive type
  return send(key) if key == :index

  json_key = Util.camelize(key.to_s)
  return values[json_key] unless self.class.has_svm

  # prioritize dirty attributes, then staged, then value
  # ideally we should use only dirty attributes, done by executing .apply_attributes
  return @dirty_attributes[key] if @dirty_attributes.include?(key)
  # for primitive types we should just return staged or value
  return staged || value if key == :primitive
  return staged.send(key) if staged.respond_to?(key)

  value.send(key) if value.respond_to?(key)
end

#model_nameObject



181
182
183
# File 'lib/alula/dcp_resource.rb', line 181

def model_name
  self.class
end

#pick_value_for_key(val, ruby_key) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'lib/alula/dcp_resource.rb', line 130

def pick_value_for_key(val, ruby_key)
  if val.is_a? Array
    val.map { |v| parse_value(v, ruby_key) }
  elsif val.is_a?(Alula::Dcp::ObjectField) || val.is_a?(Alula::DcpResource)
    val.as_json
  else
    parse_value(val, ruby_key)
  end
end

#reconstruct_from(device_id, json_object) ⇒ Object



85
86
87
# File 'lib/alula/dcp_resource.rb', line 85

def reconstruct_from(device_id, json_object)
  construct_from(device_id, json_object)
end

#refreshObject



93
94
95
96
97
98
99
100
101
102
103
# File 'lib/alula/dcp_resource.rb', line 93

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