Module: SkullIsland::Helpers::Resource

Included in:
Resource
Defined in:
lib/skull_island/helpers/resource.rb

Overview

Simple helper methods for Resources

Instance Method Summary collapse

Instance Method Details

#<=>(other) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
# File 'lib/skull_island/helpers/resource.rb', line 241

def <=>(other)
  if id < other.id
    -1
  elsif id > other.id
    1
  elsif id == other.id
    0
  else
    raise Exceptions::InvalidArguments
  end
end

#datetime_from_params(params, actual_key) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'lib/skull_island/helpers/resource.rb', line 7

def datetime_from_params(params, actual_key)
  DateTime.new(
    params["#{actual_key}(1i)"].to_i,
    params["#{actual_key}(2i)"].to_i,
    params["#{actual_key}(3i)"].to_i,
    params["#{actual_key}(4i)"].to_i,
    params["#{actual_key}(5i)"].to_i
  )
end

#delayed_set(property, data, key = property.to_s) ⇒ Object

rubocop:disable Style/GuardClause rubocop:disable Security/Eval



19
20
21
22
23
24
25
26
27
# File 'lib/skull_island/helpers/resource.rb', line 19

def delayed_set(property, data, key = property.to_s)
  if data[key]
    value = recursive_erubi(data[key])
    send(
      "#{property}=".to_sym,
      value.is_a?(String) && value.start_with?('{"') ? eval(value) : value
    )
  end
end

#destroyObject



166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/skull_island/helpers/resource.rb', line 166

def destroy
  raise Exceptions::ImmutableModification if immutable?

  unless new?
    @api_client.delete(relative_uri.to_s)
    @api_client.invalidate_cache_for(relative_uri.to_s)
    @lazy = false
    @tainted = true
    @entity.delete('id')
  end
  true
end

#digestObject

rubocop:enable Security/Eval rubocop:enable Style/GuardClause



43
44
45
46
47
# File 'lib/skull_island/helpers/resource.rb', line 43

def digest
  Digest::MD5.hexdigest(
    digest_properties.sort.map { |prp| "#{prp}=#{send(prp.to_sym) || ''}" }.compact.join(':')
  )
end

#digest_propertiesObject



49
50
51
52
# File 'lib/skull_island/helpers/resource.rb', line 49

def digest_properties
  props = properties.keys.reject { |k| %i[created_at updated_at].include? k }
  supports_meta? ? props + [:project] : props
end

#find_by_digestObject

Tests for an existing version of this resource based on its properties rather than its ‘id`



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/skull_island/helpers/resource.rb', line 55

def find_by_digest
  result = self.class.where(:digest, digest) # matching digest means the equivalent resource
  if result.size == 1
    entity_data = @api_client.cache(result.first.relative_uri.to_s) do |client|
      client.get(result.first.relative_uri.to_s)
    end
    @entity = entity_data
    @lazy = false
    @tainted = false
    true
  else
    false
  end
end

#fresh?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/skull_island/helpers/resource.rb', line 70

def fresh?
  !tainted?
end

#host_regexObject



74
75
76
# File 'lib/skull_island/helpers/resource.rb', line 74

def host_regex
  /^(([\w]|[\w][\w\-]*[\w])\.)*([\w]|[\w][\w\-]*[\w])$/
end

#idObject



82
83
84
# File 'lib/skull_island/helpers/resource.rb', line 82

def id
  @entity[id_property.to_s]
end

#id_propertyObject



78
79
80
# File 'lib/skull_island/helpers/resource.rb', line 78

def id_property
  self.class.properties.select { |_, opts| opts[:id_property] }.keys.first || 'id'
end

#immutable?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/skull_island/helpers/resource.rb', line 86

def immutable?
  self.class.immutable?
end

#import_update_or_skip(verbose: false, test: false, index:) ⇒ Object

rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/skull_island/helpers/resource.rb', line 92

def import_update_or_skip(verbose: false, test: false, index:)
  if find_by_digest
    puts "[INFO] Skipping #{self.class} index #{index} (#{id})" if verbose
  elsif test
    puts "[INFO] Would have saved #{self.class} index #{index}"
  elsif modified_existing?
    puts "[INFO] Modified #{self.class} index #{index} (#{id})" if verbose
  elsif save
    puts "[INFO] Created #{self.class} index #{index} (#{id})" if verbose
  else
    puts "[ERR] Failed to save #{self.class} index #{index}"
  end
end

#lookup(type, value) ⇒ Object

rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/PerceivedComplexity



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/skull_island/helpers/resource.rb', line 108

def lookup(type, value)
  case type
  when :consumer
    { 'id' => Resources::Consumer.find(:username, value).id }
  when :route
    { 'id' => Resources::Route.find(:name, value).id }
  when :service
    { 'id' => Resources::Service.find(:name, value).id }
  when :upstream
    { 'id' => Resources::Upstream.find(:name, value).id }
  else
    raise Exceptions::InvalidArguments, "#{type} is not a valid lookup type"
  end
end

#model_nameObject

ActiveRecord ActiveModel::Name compatibility method



124
125
126
# File 'lib/skull_island/helpers/resource.rb', line 124

def model_name
  self.class
end

#new?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'lib/skull_island/helpers/resource.rb', line 128

def new?
  !@entity.key?(id_property.to_s)
end

#persisted?Boolean

ActiveRecord ActiveModel::Model compatibility method

Returns:

  • (Boolean)


133
134
135
# File 'lib/skull_island/helpers/resource.rb', line 133

def persisted?
  !new?
end

#postprocess_created_at(value) ⇒ Object



137
138
139
# File 'lib/skull_island/helpers/resource.rb', line 137

def postprocess_created_at(value)
  Time.at(value).utc.to_datetime
end

#postprocess_updated_at(value) ⇒ Object



141
142
143
# File 'lib/skull_island/helpers/resource.rb', line 141

def postprocess_updated_at(value)
  Time.at(value).utc.to_datetime
end

#propertiesObject



145
146
147
# File 'lib/skull_island/helpers/resource.rb', line 145

def properties
  self.class.properties
end

#prune_for_save(data) ⇒ Object



253
254
255
256
257
258
259
260
# File 'lib/skull_island/helpers/resource.rb', line 253

def prune_for_save(data)
  data.reject do |k, v|
    k.to_sym == id_property ||
      !properties[k.to_sym] ||
      properties[k.to_sym][:read_only] ||
      v.nil?
  end
end

#recursive_erubi(data) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/skull_island/helpers/resource.rb', line 29

def recursive_erubi(data)
  if data.is_a?(String)
    eval(Erubi::Engine.new(data).src)
  elsif data.is_a?(Array)
    data.map { |item| recursive_erubi(item) }
  elsif data.is_a?(Hash)
    data.map { |k, v| [k, recursive_erubi(v)] }.to_h
  else
    data
  end
end

#reloadObject



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/skull_island/helpers/resource.rb', line 179

def reload
  if new?
    # Can't reload a new resource
    false
  else
    @api_client.invalidate_cache_for(relative_uri.to_s)
    entity_data = @api_client.cache(relative_uri.to_s) do |client|
      client.get(relative_uri.to_s)
    end
    @entity = entity_data
    @lazy = false
    @tainted = false
    true
  end
end

#required_propertiesObject



149
150
151
# File 'lib/skull_island/helpers/resource.rb', line 149

def required_properties
  properties.select { |_key, value| value[:required] }
end

#saveObject



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/skull_island/helpers/resource.rb', line 195

def save
  saveable_data = prune_for_save(@entity)
  validate_required_properties(saveable_data)

  if new?
    @entity  = @api_client.post(save_uri.to_s, saveable_data)
    @lazy    = true
  else
    @api_client.invalidate_cache_for(relative_uri.to_s)
    @entity = @api_client.patch(relative_uri, saveable_data)
  end
  @api_client.invalidate_cache_for(self.class.relative_uri.to_s) # clear any collection class
  @tainted = false
  true
end

#save_uriObject



211
212
213
# File 'lib/skull_island/helpers/resource.rb', line 211

def save_uri
  self.class.relative_uri
end

#supports_meta?Boolean

Returns:

  • (Boolean)


215
216
217
# File 'lib/skull_island/helpers/resource.rb', line 215

def supports_meta?
  false
end

#tainted?Boolean

Returns:

  • (Boolean)


153
154
155
# File 'lib/skull_island/helpers/resource.rb', line 153

def tainted?
  @tainted ? true : false
end

#to_paramObject

ActiveRecord ActiveModel::Conversion compatibility method



158
159
160
# File 'lib/skull_island/helpers/resource.rb', line 158

def to_param
  new? ? nil : id.to_s
end

#to_sObject



162
163
164
# File 'lib/skull_island/helpers/resource.rb', line 162

def to_s
  to_param.to_s
end

#update(params) ⇒ Object

ActiveRecord ActiveModel compatibility method



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/skull_island/helpers/resource.rb', line 220

def update(params)
  new_params = {}
  # need to convert multi-part datetime params
  params.each do |key, value|
    if /([^(]+)\(1i/.match?(key)
      actual_key = key.match(/([^(]+)\(/)[1]
      new_params[actual_key] = datetime_from_params(params, actual_key)
    else
      new_params[key] = value
    end
  end

  new_params.each do |key, value|
    setter_key = "#{key}=".to_sym
    raise Exceptions::InvalidProperty unless respond_to?(setter_key)

    send(setter_key, value)
  end
  save
end