Module: Alula::Dcp::ResourceAttributes

Defined Under Namespace

Modules: InstanceMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/alula/dcp/resource_attributes.rb', line 8

def self.extended(base)
  base.class_eval do
    class << self
      attr_writer :has_svm

      def has_svm
        @has_svm ||= false
      end
    end
    @resource_path = nil
    @type = nil
    @http_methods = []
    @fields = {}

    def mark_dirty(field_name, old_value, new_value)
      @dirty_attributes << field_name if old_value != new_value
    end
  end
  base.include(InstanceMethods)
end

Instance Method Details

#date_fieldsObject



130
131
132
133
134
135
# File 'lib/alula/dcp/resource_attributes.rb', line 130

def date_fields
  @date_fields ||=
    get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
      collector << field_name if opts[:type].to_sym == :date
    end
end

#field(field_name, **opts) ⇒ Object

Memoizes field names and options



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_attributes.rb', line 62

def field(field_name, **opts)
  @fields ||= {}
  @fields[field_name] = opts
  return if has_svm && field_name != :index

  json_key = Alula::Util.camelize(field_name)
  instance_eval do
    # Reader method for attribute
    define_method(field_name) do
      value = @values[json_key]
      if opts[:type] == :date && ![nil, ''].include?(value)
        begin
          DateTime.parse(value)
        rescue ArgumentError
          value
        end
      elsif opts[:type] == :object && opts[:use] && !value.nil? && value.respond_to?(:each)
        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] && !value.nil? && value.respond_to?(:each)
        # 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
      elsif opts[:type] == :boolean
        [true, 'true', 1, '1'].include? value
      elsif opts[:type] == :number
        value&.to_i
      else
        value
      end
    end

    # Setter method
    define_method("#{field_name}=") do |new_value|
      #
      # 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 == ''

      new_value = [true, 'true', 1, '1'].include? new_value if opts[:type] == :boolean

      # Mark the attribute as dirty if the new value is different
      mark_dirty(field_name, @values[json_key], new_value)
      #
      # Assign the new value (always assigned even if a duplicate)
      @values[json_key] = new_value
    end
  end
end

#field_namesObject



149
150
151
# File 'lib/alula/dcp/resource_attributes.rb', line 149

def field_names
  get_fields.keys
end

#filterable_fieldsObject



137
138
139
140
141
# File 'lib/alula/dcp/resource_attributes.rb', line 137

def filterable_fields
  get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
    collector << field_name if opts[:filterable] == true
  end
end

#get_fieldsObject



119
120
121
122
123
124
125
126
127
128
# File 'lib/alula/dcp/resource_attributes.rb', line 119

def get_fields
  parent_fields = if superclass.respond_to?(:get_fields)
                    superclass.get_fields
                  else
                    {}
                  end

  @fields ||= {}
  parent_fields.merge(@fields)
end

#get_http_methodsObject



56
57
58
# File 'lib/alula/dcp/resource_attributes.rb', line 56

def get_http_methods
  @http_methods
end

#get_resource_path(index = nil) ⇒ Object



38
39
40
41
42
# File 'lib/alula/dcp/resource_attributes.rb', line 38

def get_resource_path(index = nil)
  return "#{@resource_path}/#{index}" if index

  @resource_path
end

#get_typeObject



48
49
50
# File 'lib/alula/dcp/resource_attributes.rb', line 48

def get_type
  @type
end

#http_methods(methods) ⇒ Object



52
53
54
# File 'lib/alula/dcp/resource_attributes.rb', line 52

def http_methods(methods)
  @http_methods = methods
end

#param_keyObject



153
154
155
156
157
# File 'lib/alula/dcp/resource_attributes.rb', line 153

def param_key
  # return only the last part of the class name, in snake_case
  # e.g. Alula::Dcp::Config::PanelOptions becomes panel_options
  Util.underscore(name.split('::')[-1])
end

#resource_path(name) ⇒ Object

Class methods for defining how fields and types work NOTE: We're not using real getters and setters here. I want the method signature to match how most other Ruby class configuration is done, and that is with simple methods that take params.



34
35
36
# File 'lib/alula/dcp/resource_attributes.rb', line 34

def resource_path(name)
  @resource_path = name
end

#sortable_fieldsObject



143
144
145
146
147
# File 'lib/alula/dcp/resource_attributes.rb', line 143

def sortable_fields
  get_fields.each_pair.each_with_object([]) do |(field_name, opts), collector|
    collector << field_name if opts[:sortable] == true
  end
end

#type(type) ⇒ Object



44
45
46
# File 'lib/alula/dcp/resource_attributes.rb', line 44

def type(type)
  @type = type
end