Class: Alula::Dcp::ResourceState

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

Direct Known Subclasses

StagedState, ValueState

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(resource, key) ⇒ ResourceState

Returns a new instance of ResourceState.



8
9
10
11
# File 'lib/alula/dcp/resource_state.rb', line 8

def initialize(resource, key)
  @resource = resource
  @key = key
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object (private)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/alula/dcp/resource_state.rb', line 25

def method_missing(name, *args)
  field_name = name.to_s.sub(/=$/, '').to_sym
  klass = get_discriminated_class(@resource.values)
  if klass.get_fields.key?(field_name)
    json_key = Util.camelize(field_name.to_s)
    opts = klass.get_fields[field_name]
    if name.to_s.end_with?('=')
      # Setter method
      define_singleton_method("#{field_name}=") do |new_value|
        # transform keys inside new_value to camelCase
        new_value = new_value.transform_keys { |k| Util.camelize(k.to_s) } if new_value.is_a?(Hash)
        #
        # Coerce 'blank like' fields into a defined blank value
        # This helps HTML form submissions. A blank text field comes through as an
        # empty string, instead of a nil as the API validates for.
        new_value = nil if new_value == '' && opts[:type] != :string

        new_value = [true, 'true', 1, '1'].include? new_value if opts[:type] == :boolean
        new_value = new_value.to_i if opts[:type] == :number
        if opts[:type] == :object && opts[:use]
          obj_fields = opts[:use].get_fields
          new_value.each do |k, v|
            next unless obj_fields.key?(k.to_sym)

            type = obj_fields[k.to_sym][:type]
            case type
            when :boolean
              new_value[k] = [true, 'true', 1, '1'].include? v
            when :number
              new_value[k] = v.to_i
            else
              # For other types, just assign the value directly
              new_value[k] = v
            end
          end
        end
        #
        # Assign the new value (always assigned even if a duplicate)
        @resource.values[@key][json_key] = new_value
      end
      send("#{field_name}=", *args)
    else
      define_singleton_method(field_name) do
        value = @resource.values[@key][json_key]
        return nil if value.nil?

        # Regular type handling
        if opts[:type] == :date && ![nil, ''].include?(value)
          begin
            DateTime.parse(value)
          rescue ArgumentError
            value
          end
        elsif opts[:type] == :object && opts[:use]
          if opts[:use].superclass == Alula::Dcp::ObjectField
            opts[:use].new({}, field_name, value)
          elsif respond_to?(:device_id)
            opts[:use].new(device_id, value)
          else
            opts[:use].new(nil, value)
          end
        elsif opts[:type] == :array && opts[:of]
          if primitive_use?(opts[:of])
            # Array of primitives, e.g. :boolean, :number, :string
            value.map do |item|
              if opts[:of] == :boolean
                [true, 'true', 1, '1'].include? item
              elsif opts[:of] == :number
                item.to_i
              else
                item
              end
            end
          else
            # Array of objects, each object is a new instance of the use class
            value.each_with_object([]) do |item, collector|
              collector << opts[:of].new(device_id, item)
            end
          end
        elsif opts[:type] == :boolean
          [true, 'true', 1, '1'].include? value
        elsif opts[:type] == :number
          value&.to_i
        else
          value
        end
      end
      send(field_name)
    end
  else
    super
  end
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



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

def key
  @key
end

Instance Method Details

#apply_attributes(attributes, _opts = {}) ⇒ Object



17
18
19
20
21
# File 'lib/alula/dcp/resource_state.rb', line 17

def apply_attributes(attributes, _opts = {})
  attributes.each do |key, value|
    send("#{key}=", value) if respond_to?("#{key}=")
  end
end

#model_nameObject



13
14
15
# File 'lib/alula/dcp/resource_state.rb', line 13

def model_name
  @resource.class
end