Module: MasterView::DirectiveLoadPath

Defined in:
lib/masterview/directive_load_path.rb

Overview

The directive load path supports configuring a MasterView application with a list of directories from which directives are loaded.

A MasterView application is always configured with the standard set of built-in directives, customarily referenced in templates in the mv: namespace. Additional directives can be used by appending directories containing the directive implementations to the MasterView load path specified by the Configuration.

Defined Under Namespace

Classes: Path, PathEntry

Constant Summary collapse

METADATA_SPECS_FILE_NAME =

File name of metadata specs file in a directives directory Contains yaml specifications for directive implementations

'.metadata'
DEBUG_MD_DIR_SPECS =

:nodoc: ##DEBUG##

false
@@path_registry =

:nodoc:

{}

Class Method Summary collapse

Class Method Details

.clean_path(path, options) ⇒ Object

Answer a clean path with a single entry for each directory and path entries validated and normalize.

Specify option :dup_policy ::= { :merge || :use_latest } for handling options on dup entries (merge or use the last-defined options).

Optionally provide a block arg for handling validation exceptions



301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/masterview/directive_load_path.rb', line 301

def self.clean_path(path, options)

  dup_policy = options.fetch( :dup_policy, :use_latest )
  
  unique_paths = []
  path_entries = {}
  path.each { | dpe |
    begin
      dpe.validate()
      dpe.normalize()
      dir_path = dpe.dir_path
      if ! unique_paths.include?(dir_path)
        unique_paths << dir_path
      else
        # dup entry - we've already got this dir_path registered
        if dup_policy == :merge
          prev_options = path_entries[dir_path].options
          options = prev_options.merge(dpe.options)
        else # :use_latest
          options = dpe.options  # last-registered path entry wins
        end
        # replace path entry with merged or replaced options
        dpe = PathEntry.new(dir_path, options)
      end
      path_entries[dir_path] = dpe
    rescue InvalidDirectivePathError => ex
      if block_given?
        yield(ex)
      else
        raise
      end
    end
  }

  clean_path = Path.new
  unique_paths.each { | dir_path | 
      clean_path << path_entries[dir_path]
  }
  clean_path

end

.clone_path(path) ⇒ Object

Answer a clone copy of a directive load path

Does a deep_copy to ensure a clean copy of options maps



74
75
76
# File 'lib/masterview/directive_load_path.rb', line 74

def self.clone_path(path)
  path.collect{ | dpe | dpe.deep_copy }
end

.compute_md_defaults(default_md_specs, dir_md_defaults, path_entry_defaults) ⇒ Object

Compute the metadata default specs for a directives directory Path entry options override/extend directory .metadata specs



375
376
377
378
379
380
381
382
383
384
# File 'lib/masterview/directive_load_path.rb', line 375

def self.compute_md_defaults(default_md_specs, dir_md_defaults, path_entry_defaults)
  md_defaults = {}
  md_defaults.merge! default_md_specs  # we always start with the app-wide defaults
  md_defaults.merge! dir_md_defaults   # bring in specs from the directory .metadata
  md_defaults.merge! path_entry_defaults  # and allow app ovveride on path entry config
  # raises ArgumentError if props are bad
  # should be superfluous because we've already done this on each individual set of defaults
  . md_defaults
  md_defaults
end

.currentObject

Answer the directives load path specs for the current load path



47
48
49
# File 'lib/masterview/directive_load_path.rb', line 47

def self.current
  @@path_registry[:current]
end

.default_path_specsObject

Answer the default directives load path specs



52
53
54
# File 'lib/masterview/directive_load_path.rb', line 52

def self.default_path_specs #:nodoc:
  @@path_registry[:default]
end

.default_path_specs=(load_path) ⇒ Object

Install the configured load path



57
58
59
60
61
62
# File 'lib/masterview/directive_load_path.rb', line 57

def self.default_path_specs=(load_path) #:nodoc:
  @@path_registry[:default] = load_path.nil?  ? nil : clone_path(load_path)
  if load_path && ! @@path_registry.has_key?(:current)
    @@path_registry[:current] = clone_path(load_path) 
  end
end

.load_metadata_specs(file_path) ⇒ Object

Load a metadata specifications file.

Normalizes options hash keys to symbols. Should ordinarily be used through PathEntry.load_metadata_specs.



348
349
350
351
352
353
# File 'lib/masterview/directive_load_path.rb', line 348

def self.(file_path)
md_config_specs = YAML::load(IO.read(file_path))
#?what does yaml do with an empy file?? return {} if md_config_specs.nil?
#assert md_config_specs.is_a?(Hash)
symbolize_options_hash_keys(md_config_specs)
end

.path_registryObject

cattr_reader :path_registry



42
43
44
# File 'lib/masterview/directive_load_path.rb', line 42

def self.path_registry  #:nodoc: # special hook for test cases fiddling with system state
  @@path_registry
end

.reset_currentObject

hook for test cases so they can ensure a clean system state



65
66
67
68
# File 'lib/masterview/directive_load_path.rb', line 65

def self.reset_current()  #:nodoc:
  load_path = self.default_path_specs
  @@path_registry[:current] = load_path.nil?  ? nil : clone_path(load_path)
end

.symbolize_options_hash_keys(data) ⇒ Object

do in-place symbolization of keys; recurse



356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
# File 'lib/masterview/directive_load_path.rb', line 356

def self.symbolize_options_hash_keys(data) #:nodoc:
  #data.symbolize_keys!
  original_keys = data.keys()
  original_keys.each { | key |
    value = data[key]
    symbolizing_value = value.is_a?(Hash)
    value = symbolize_options_hash_keys(value) if symbolizing_value
    if ! key.is_a?(Symbol)
      data[key.to_sym] = value
      data.delete(key)
    elsif symbolizing_value
      data[key] = value
    end
  }
  data
end