Class: KManager::Resources::BaseResource

Inherits:
Object
  • Object
show all
Includes:
KDoc::Guarded, KLog::Logging
Defined in:
lib/k_manager/resources/base_resource.rb

Overview

A resource represents text based content in the project. The content maybe data, interpreted ruby code or a combination of the two.

Any non-binary file that is useful for processing.

Currently resources refer to file based content, but it is envisaged that resources could come from a distributed source such as Gist, WebService, or even FTP.

Resources can hold different types of static and smart content. Examples of static content include JSON, YAML and CSV Example of smart content include Ruby classes, PORO’s and DSL’s.

NOTE: The resource represents the text content, but not the actual data or code that resides there. Instead a document is created to store the data or code. The reason for this is that some content files, especially DSL’s may have more then one interpreted ruby structure included in the content and so a document gets created for each DSL, but for all other files, there is generally only one document.

Direct Known Subclasses

FileResource, MemResource, WebResource

Constant Summary collapse

ACTIONS =
%i[load_content register_document preload_document load_document].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, **opts) ⇒ BaseResource

Initialize base for resources

NAMESPACE can probably be taken from file set relative path

Parameters:

  • **opts (Hash)

    Options for initializing the resource

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :project (Project)

    attach the resource to a project



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/k_manager/resources/base_resource.rb', line 88

def initialize(uri, **opts)
  self.uri      = uri

  @status       = :alive
  @area         = value_remove(opts, :area)
  @namespace    = value_remove(opts, :namespace)
  @content_type = @content_type || value_remove(opts, :content_type) || infer_content_type || default_content_type
  @content      = value_remove(opts, :content)

  # attach_project(opts[:project]) if opts[:project]
  @documents = []
end

Instance Attribute Details

#areaObject

TODO: Write Test Area is an option property what will only be set when working with Area



66
67
68
# File 'lib/k_manager/resources/base_resource.rb', line 66

def area
  @area
end

#contentObject (readonly)

Content of resource, use read content to load this property



72
73
74
# File 'lib/k_manager/resources/base_resource.rb', line 72

def content
  @content
end

#content_typeObject (readonly)

What content type does the underlying resource type generally contain

Examples:

:csv - CSV text content :json - JSON text content :yaml - YAML text content :xml - XML text content :ruby - Ruby code file of unknown capability :ruby_dsl - Ruby code holding some type of known DSL such as a KDoc

DISCUSS: should this subtype be delegated to an attribute on a responsible class


62
63
64
# File 'lib/k_manager/resources/base_resource.rb', line 62

def content_type
  @content_type
end

#documentsObject

List of documents derived from this resource

Most resources will create one document, but a DSL can generate multiple documents and some future resources may do as well

Currently there will always be a minimum of 1 document even if the resource is not a data resource, e.g. Ruby class



81
82
83
# File 'lib/k_manager/resources/base_resource.rb', line 81

def documents
  @documents
end

#namespaceObject (readonly)

Optional namespace that the resource belongs to.



69
70
71
# File 'lib/k_manager/resources/base_resource.rb', line 69

def namespace
  @namespace
end

#statusObject (readonly)

TODO: Refactor from status to state and extract to a State class Status of the resource

  • :alive (i am alive, or instantiated)

  • :content_loading

  • :content_loaded

  • :documents_registering

  • :documents_registered

  • :documents_preloading

  • :documents_preloaded

  • :documents_loading

  • :documents_loaded



49
50
51
# File 'lib/k_manager/resources/base_resource.rb', line 49

def status
  @status
end

#uriObject



36
37
38
# File 'lib/k_manager/resources/base_resource.rb', line 36

def uri
  @uri
end

Class Method Details

.valid_action?(action) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/k_manager/resources/base_resource.rb', line 31

def valid_action?(action)
  ACTIONS.include?(action)
end

Instance Method Details

#activated?Boolean

TODO: Is this really needed? def document

@document ||= documents&.first

end

Returns:

  • (Boolean)


111
112
113
114
115
116
117
118
# File 'lib/k_manager/resources/base_resource.rb', line 111

def activated?
  # log.section_heading("Am I activated?")
  # log.kv 'URI', uri
  # log.kv 'ACTIVE URI', self.area.manager.active_uri
  return false if area.nil?

  uri.to_s == area.manager.active_uri.to_s
end

#alive?Boolean

Returns:

  • (Boolean)


248
249
250
# File 'lib/k_manager/resources/base_resource.rb', line 248

def alive?
  @status == :alive
end

#attach_document(document, change_content_type: nil) ⇒ Object



212
213
214
215
216
217
218
# File 'lib/k_manager/resources/base_resource.rb', line 212

def attach_document(document, change_content_type: nil)
  @content_type = change_content_type if change_content_type

  document.owner = self
  @documents << document
  document
end

#attribute_values(prefix = nil) ⇒ Object

rubocop:disable Metrics/AbcSize



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/k_manager/resources/base_resource.rb', line 281

def attribute_values(prefix = nil)
  result = {}
  result["#{prefix}id".to_sym]              = object_id
  result["#{prefix}key".to_sym]             = infer_key
  result["#{prefix}namespace".to_sym]       = namespace
  result["#{prefix}status".to_sym]          = status
  result["#{prefix}source".to_sym]          = source_path
  result["#{prefix}content_type".to_sym]    = content_type
  result["#{prefix}content".to_sym]         = content
  result["#{prefix}document_count".to_sym]  = documents.length
  result["#{prefix}errors".to_sym]          = error_hash
  result["#{prefix}valid".to_sym]           = valid?
  result["#{prefix}scheme".to_sym]          = scheme
  result["#{prefix}host".to_sym]            = host
  result
end

#content_loaded?Boolean

Returns:

  • (Boolean)


252
253
254
# File 'lib/k_manager/resources/base_resource.rb', line 252

def content_loaded?
  @status == :content_loaded
end

#debug(heading = 'resource') ⇒ Object

rubocop:disable Metrics/AbcSize



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/k_manager/resources/base_resource.rb', line 300

def debug(heading = 'resource')
  width = 20
  log.section_heading(heading)
  log.kv 'area'             , area.name                                             , width if area
  log.kv 'area namespace'   , area.namespace                                        , width if area
  log.kv 'scheme'           , scheme                                                , width
  log.kv 'host'             , host , width
  log.kv 'source_path'      , source_path                                           , width
  log.kv 'content_type'     , content_type                                          , width
  log.kv 'status'           , status                                                , width
  log.kv 'content'          , content.nil? ? '' : content[0..100].gsub("\n", '\n')  , width
  log.kv 'documents'        , documents.length                                      , width

  yield if block_given?

  log_any_messages

  # log.kv 'infer_key', infer_key                                             , width
  # log.kv 'project'  , project

  documents.each(&:debug)
  nil
end

#default_content_typeObject



244
245
246
# File 'lib/k_manager/resources/base_resource.rb', line 244

def default_content_type
  :unknown
end

#default_schemeObject

What schema does the underlying resource connect with by default

Examples:

:file :web (http: https: fpt:) :mem - some type of memory structure



235
236
237
# File 'lib/k_manager/resources/base_resource.rb', line 235

def default_scheme
  :unknown
end

#documents_loaded?Boolean

Returns:

  • (Boolean)


264
265
266
# File 'lib/k_manager/resources/base_resource.rb', line 264

def documents_loaded?
  @status == :documents_loaded
end

#documents_preloaded?Boolean

Returns:

  • (Boolean)


260
261
262
# File 'lib/k_manager/resources/base_resource.rb', line 260

def documents_preloaded?
  @status == :documents_preloaded
end

#documents_registered?Boolean

Returns:

  • (Boolean)


256
257
258
# File 'lib/k_manager/resources/base_resource.rb', line 256

def documents_registered?
  @status == :documents_registered
end

#fire_action(action) ⇒ Object

Fire actions and keep track of status as they fire

rubocop:disable Metrics/CyclomaticComplexity

Parameters:

  • action (Symbol)

    what action is to be fired

    • :load_content for loading text content

    • :register_document for registering 1 or more documents (name and namespace) against the resource

    • :preload_document for parsing the content into a document

    • :load_document for finalizing the document load with met dependencies and action execution if applicable



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/k_manager/resources/base_resource.rb', line 128

def fire_action(action)
  # TODO: Write test for valid
  return unless valid?

  case action
  when :load_content
    load_content_action if alive?
  when :register_document
    register_document_action if content_loaded?
  when :preload_document
    preload_document_action if documents_registered?
  when :load_document
    load_document_action if documents_preloaded?
  else
    log.warn "Action: '#{action}' is invalid for status: '#{status}'"
  end
end

#fire_next_actionObject

I don’t think this is needed, it is never really used



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/k_manager/resources/base_resource.rb', line 148

def fire_next_action
  if alive?
    fire_action(:load_content)
  elsif content_loaded?
    fire_action(:register_document)
  elsif documents_registered?
    fire_action(:preload_document)
  elsif documents_preloaded?
    fire_action(:load_document)
  end
end

#hostObject



224
225
226
# File 'lib/k_manager/resources/base_resource.rb', line 224

def host
  uri&.host
end

#infer_content_typeObject

Optionally overridden, this is the case with FileResource



240
241
242
# File 'lib/k_manager/resources/base_resource.rb', line 240

def infer_content_type
  nil
end

#infer_keyObject

What identifying key does this resource have?

Child resources will have different ways of working this out, eg. File Resources will use the file name.



164
165
166
# File 'lib/k_manager/resources/base_resource.rb', line 164

def infer_key
  nil
end

#load_contentObject



168
169
170
# File 'lib/k_manager/resources/base_resource.rb', line 168

def load_content
  # log.warn 'you need to implement load_content'
end

#load_documentObject

rubocop:disable Lint/RescueException



188
189
190
191
192
193
194
195
196
197
# File 'lib/k_manager/resources/base_resource.rb', line 188

def load_document
  documents.each do |document|
    document.execute_block(run_actions: activated?)
  end
rescue Exception => e
  guard(e.message)
  debug
  log.exception(e, style: KManager.opts.exception_style)
  # log.exception(e, style: :short)
end

#new_document(data) ⇒ Object

This is when you need a simple container



201
202
203
204
205
206
207
208
209
210
# File 'lib/k_manager/resources/base_resource.rb', line 201

def new_document(data)
  document = KDoc::Container.new(
    key: infer_key,
    type: content_type,
    namespace: namespace,
    default_data_type: data.class,
    data: data
  )
  attach_document(document)
end

#preload_documentObject

rubocop:disable Lint/RescueException



177
178
179
180
181
182
183
184
# File 'lib/k_manager/resources/base_resource.rb', line 177

def preload_document
  documents.each(&:execute_block)
rescue Exception => e
  guard(e.message)
  debug
  log.exception(e, style: KManager.opts.exception_style)
  # log.exception(e, style: :short)
end

#register_documentObject



172
173
174
# File 'lib/k_manager/resources/base_resource.rb', line 172

def register_document
  KManager::Resources::ResourceDocumentFactory.create_documents(self)
end

#schemeObject



220
221
222
# File 'lib/k_manager/resources/base_resource.rb', line 220

def scheme
  uri&.scheme&.to_sym || default_scheme
end

#source_pathObject



101
102
103
104
# File 'lib/k_manager/resources/base_resource.rb', line 101

def source_path
  # Expectation that uri is of type URI::HTTP or URI::HTTPS
  uri.to_s
end