lib/middleman-core/core_extensions/data/controller.rb
require 'hamster' require 'middleman-core/util/data' require 'middleman-core/core_extensions/data/stores/local_file' require 'middleman-core/core_extensions/data/stores/in_memory' require 'middleman-core/core_extensions/data/proxies/array' require 'middleman-core/core_extensions/data/proxies/hash' module Middleman module CoreExtensions module Data # The core logic behind the data extension. class DataStoreController extend Forwardable def_delegator :@local_file_data_store, :update_files def_delegators :@in_memory_data_store, :store, :callbacks def initialize(app, track_data_access) @data_collection_depth = app.config[:data_collection_depth] @track_data_access = track_data_access @local_file_data_store = Data::Stores::LocalFileDataStore.new(app) @in_memory_data_store = Data::Stores::InMemoryDataStore.new # Sorted in order of access precedence. @data_stores = [ @local_file_data_store, @in_memory_data_store ] @enhanced_cache = {} end def key?(k) @data_stores.any? { |s| s.key?(k) } end alias has_key? key? def key(k) source = @data_stores.find { |s| s.key?(k) } source[k] unless source.nil? end alias [] key def vertices @data_stores.reduce(::Hamster::Set.empty) do |sum, s| sum | s.vertices end end def enhanced_data(k) value = key(k) if @enhanced_cache.key?(k) cached_id, cached_value = @enhanced_cache[k] return cached_value if cached_id == value.object_id @enhanced_cache.delete(k) end enhanced = ::Middleman::Util.recursively_enhance(value) @enhanced_cache[k] = [value.object_id, enhanced] enhanced end def proxied_data(k, parent = nil) data = enhanced_data(k) return data unless @track_data_access if data.is_a? ::Middleman::Util::EnhancedHash Data::Proxies::HashProxy.new(k, data, @data_collection_depth, parent) elsif data.is_a? ::Array Data::Proxies::ArrayProxy.new(k, data, @data_collection_depth, parent) else raise 'Invalid data to wrap' end end # "Magically" find namespaces of data if they exist # # @param [String] path The namespace to search for # @return [Hash, nil] def method_missing(method) return proxied_data(method) if key?(method) super end # Needed so that method_missing makes sense def respond_to?(method, include_private = false) super || key?(method) end # Convert all the data into a static hash # # @return [Hash] def to_h @data_stores.reduce({}) do |sum, store| sum.merge(store.to_h) end end end end end end