module Ruhoh::Base::Collectable

Public Class Methods

included(klass) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 2
def self.included(klass)
  klass.__send__(:attr_accessor, :resource_name, :master)
  klass.__send__(:attr_reader, :ruhoh)
end
new(ruhoh) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 7
def initialize(ruhoh)
  @ruhoh = ruhoh
end

Public Instance Methods

_all_files() click to toggle source

Collect all files within this collection, valid or otherwise. Each resource can have 3 file references, one per each cascade level. The file hashes are collected in order and overwrite eachother if found. This is a low-level method, see files for the public interface.

@return dictionary of pointers.

# File lib/ruhoh/base/collectable.rb, line 144
def _all_files
  dict = {}
  paths.each do |path|
    FileUtils.cd(path) { 
      Dir[glob].each { |id|
        next unless File.exist?(id) && FileTest.file?(id)
        dict[id] = {
          "id" => id,
          "realpath" => File.realpath(id),
          "resource" => resource_name,
        }
      }
    }
  end

  dict
end
compiled_path() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 238
def compiled_path
  @compiled_path ||= @ruhoh.compiled_path(@ruhoh.to_url(url_endpoint))
end
config() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 78
def config
  config = @ruhoh.config[resource_name] || {}
  unless config.is_a?(Hash)
    Ruhoh.log.error("'#{resource_name}' config key in config" +
                    " is a #{config.class}; it needs to be a Hash (object).")
  end
  config
end
dictionary() click to toggle source

Public API @return dictionary of models { “id” => Model }

# File lib/ruhoh/base/collectable.rb, line 32
def dictionary
  dict = {}
  files.values.each { |pointer|
    dict.merge!({
      pointer['id'] => find(pointer)
    })
  }
  dict
end
files(id=nil) { |id, self| ... } click to toggle source

@param id [String, Array] Optional.

Collect all files for a single data resource.
Can be many files due to the cascade.

@param [block] Optional.

Implement custom validation logic by passing in a block.
The block is given (id, self) as args.
Return true/false for whether the file is valid/invalid.

@return dictionary of pointers.

# File lib/ruhoh/base/collectable.rb, line 126
def files(id=nil, &block)
  return @ruhoh.cache.get(files_cache_key) if @ruhoh.cache.get(files_cache_key)

  dict = _all_files
  dict.keep_if do |id, pointer|
    block_given? ? yield(id, self) : valid_file?(id)
  end

  @ruhoh.cache.set(files_cache_key, dict)
  dict
end
files_cache_key() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 227
def files_cache_key
  "#{ resource_name }-files"
end
find(name_or_pointer, opts={}) click to toggle source

Public API for finding a resource from this collection @param name_or_pointer [String, Hash]

Hash   - File pointer
String - id (filename) with full extension, e.g: about-me.md
String - name (filename) without the extension e.g: about-me
         Returns the first matched filename.
         See implementation for how match is determined.

@param opts [Hash] Optional options

opts[:all] - true to search all files as some may be invalid as resources

@return[model, nil] the model is always wrapped in its view.

# File lib/ruhoh/base/collectable.rb, line 22
def find(name_or_pointer, opts={})
  pointer = find_file(name_or_pointer, opts)
  return nil unless pointer

  @ruhoh.cache.get(pointer['realpath']) ||
  @ruhoh.cache.set(pointer['realpath'], load_model_view(pointer))
end
find_file(key, opts={}) click to toggle source

@param key [String, Hash]

String - id (filename) with full extension, e.g: about-me.md
String - name (filename) without the extension e.g: about-me
         Returns the first matched filename.
         See implementation for how match is determined.
Hash   - File pointer

@param opts [Hash] Optional options

opts[:all] - true to search all files as some may be invalid as resources

@return [pointer, nil]

# File lib/ruhoh/base/collectable.rb, line 104
def find_file(key, opts={})
  return key if key.is_a?(Hash) # assume valid pointer

  dict = opts[:all] ? _all_files : files

  dict[key] || dict.values.find{ |a| key == a['id'].gsub(/.[^.]+$/, '') }
end
glob() click to toggle source

The default glob for finding files. Every file in all child directories.

# File lib/ruhoh/base/collectable.rb, line 56
def glob
  "**/*"
end
load_client(opts) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 209
def load_client(opts)
  @_client ||= client.new(load_collection_view, opts)
end
load_collection_view() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 189
def load_collection_view
  @_collection_view ||= collection_view? ?
                          collection_view.new(self) :
                          self
end
load_compiler() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 213
def load_compiler
  @_compiler ||= compiler.new(load_collection_view)
end
load_model(pointer) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 195
def load_model(pointer)
  _model = model? ?
            model.new(@ruhoh, pointer) :
            Ruhoh::Base::Model.new(@ruhoh, pointer)
  _model.add_observer(self)
  _model
end
load_model_view(pointer) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 203
def load_model_view(pointer)
  model_view? ? 
    model_view.new(load_model(pointer)) :
    Ruhoh::Base::ModelView.new(load_model(pointer))
end
load_previewer(*args) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 223
def load_previewer(*args)
  @_previewer ||= previewer.new(@ruhoh)
end
load_watcher(*args) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 217
def load_watcher(*args)
  @_watcher ||= watcher? ?
    watcher.new(load_collection_view) :
    Ruhoh::Base::Watcher.new(load_collection_view)
end
paths() click to toggle source

Default paths to the 3 levels of the cascade.

# File lib/ruhoh/base/collectable.rb, line 61
def paths
  Array(@ruhoh.cascade.paths.map{|h| h["path"]}).map { |path|
    collection_path = File.join(path, resource_name)
    next unless File.directory?(collection_path)

    collection_path
  }.compact
end
paths?() click to toggle source

Does this resource have any valid paths to process? A valid path may exist on any of the cascade levels. False means there are no directories on any cascade level. @returns

# File lib/ruhoh/base/collectable.rb, line 74
def paths?
  !paths.empty?
end
resource_name() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 42
def resource_name
  @resource_name ||= self.class.name.split("::").pop
end
scaffold() click to toggle source
# File lib/ruhoh/base/collectable.rb, line 231
def scaffold
  pointer = find_file('_scaffold', all: true) || @ruhoh.cascade.find_file('_scaffold')
  return '' unless pointer

  File.open(pointer['realpath'], 'r:UTF-8') { |f| f.read }
end
touch(name_or_pointer) click to toggle source

NOOP touch a model. Used to perform custom regeneration logic against a model.

# File lib/ruhoh/base/collectable.rb, line 90
def touch(name_or_pointer)
end
update(model_data) click to toggle source

Implemented via Observable module See ruby-doc.org/stdlib-1.9.3/libdoc/observer/rdoc/Observable.html Collection subscribes to its child models. update is called on model process. noop

# File lib/ruhoh/base/collectable.rb, line 51
def update(model_data)
end
valid_file?(filepath) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 162
def valid_file?(filepath)
  return false if filepath.start_with?('.')
  return false if filepath.start_with?('_')
  return false if  %w{ config.json config.yaml config.yml }.include?(filepath)
  excludes = Array(config['exclude']).map { |node| Regexp.new(node) }
  excludes.each { |regex| return false if filepath =~ regex }
  true
end

Protected Instance Methods

camelize(name) click to toggle source
# File lib/ruhoh/base/collectable.rb, line 270
def camelize(name)
  name.to_s.split('_').map { |a| a.capitalize }.join
end
get_module_namespace() click to toggle source

Load the registered resource else default to Pages if not configured. @returns the resource’s module namespace

# File lib/ruhoh/base/collectable.rb, line 246
def get_module_namespace
  type = @ruhoh.config[resource_name]["use"] rescue nil
  if type
    if @ruhoh.collections.registered.include?(type)
      Ruhoh::Resources.const_get(camelize(type))
    elsif @ruhoh.collections.base.include?(type)
      Ruhoh::Base.const_get(camelize(type))
    else
      klass = camelize(type)
      Friend.say {
        red "#{resource_name} resource set to use:'#{type}' in config" +
            " but Ruhoh::Resources::#{klass} does not exist."
      }
      abort
    end
  else
    if @ruhoh.collections.registered.include?(resource_name)
      Ruhoh::Resources.const_get(camelize(resource_name))
    else
      Ruhoh::Resources.const_get(:Pages)
    end
  end
end