require 'erb' require 'md5' module Rid class Document include Attachments attr_accessor :hash, :path def initialize(options = {}) path = options[:path] path = Pathname.new(path) unless path.nil? || path.is_a?(Pathname) @path = path # build hash from options hash @hash = options[:hash] # build hash from json option self.json = options[:json] if !@hash && options[:json] @hash ||= {} end def ==(other) @hash == other.hash end # Read document from a filesystem. # # Takes a filename, # many filenames, # or an array of filenames # and assign the return value of a yielded block to the hash. # # Nested hashes # like { "hash" => { "key" => "value" } } # can be constructed if the filename contains a slash (/), # eg "hash/key". # def read!(&block) raise 'No path given!' unless @path Dir[@path.join '**/*']. map! { |file| Pathname.new file }. delete_if { |f| !f.file? }. flatten. uniq. each do |filename| key = filename.relative_path_from(@path).to_s # strip js extname from javascript files key.sub!(/\.js$/, '') unless key =~ /^_attachments/ key.sub!(/\.erb$/, '') value = block_given? ? block.call(filename) : read_file(filename) if key =~ /\.json$/ # parse json files value = JSON.parse(value) key.sub!(/\.json$/, '') else # strip value if its a one-liner value.strip! if value.count("\n") == 1 end @hash.update_at key, value end map_attachments! end # Returns a JSON string representation of the documents hash # def to_json @hash.to_json end # Build the documents hash from a JSON string # def json=(json) @hash = JSON.parse(json) end def id @id ||= @hash['_id'] @id ||= @path && File.read(@path.join('_id')).strip rescue nil end def rev @rev ||= @hash['_rev'] @rev ||= @path && File.read(@path.join('_rev')).strip rescue nil end def rev=(value) @rev = @hash['_rev'] = value if @path File.open(@path.join('_rev'), "w") { |file| file << value } end end def checksum(*files) MD5.new files.map { |f| File.read(File.join(@path, f)) }.join end private def read_file(filename) if File.extname(filename) == '.erb' ERB.new(File.read(filename)).result(binding) else File.read(filename) end end end end