lib/middleman/features/data.rb



require "yaml"
require "httparty"
require "thor"

module Middleman::Features::Data
  class << self
    def registered(app)
      app.extend ClassMethods
      app.helpers Middleman::Features::Data::Helpers
    end
    alias :included :registered
  end
  
  module Helpers
    def data
      @@data ||= Middleman::Features::Data::DataObject.new(self)
    end
  end
  
  class DataObject
    def initialize(app)
      @app = app
    end
    
    def method_missing(path)
      response = nil
      
      @@remote_sources ||= {}
      if @@remote_sources.has_key?(path.to_s)
        response = HTTParty.get(@@remote_sources[path.to_s]).parsed_response
      end
      
      file_path = File.join(@app.class.root, "data", "#{path}.yml")      
      if File.exists? file_path
        response = YAML.load_file(file_path)
      end
      
      if response
        recursively_enhance(response)
      end
    end
    
    def self.add_source(name, json_url)
      @@remote_sources ||= {}
      @@remote_sources[name.to_s] = json_url
    end
  
  private
    def recursively_enhance(data)
      if data.is_a? Hash
        data = Thor::CoreExt::HashWithIndifferentAccess.new(data)
        data.each do |key, val|
          data[key] = recursively_enhance(val)
        end
        data
      elsif data.is_a? Array
        data.each_with_index do |val, i|
          data[i] = recursively_enhance(val)
        end
        data
      else
        data
      end
    end
  end
  
  module ClassMethods
    # Makes HTTP json data available in the data object
    #
    #     data_source :my_json, "http://my/file.json"
    #
    # Available in templates as:
    #
    #     data.my_json
    def data_source(name, url)
      Middleman::Features::Data::DataObject.add_source(name, url)
    end
  end
end