require "rubygems" require "parsley" require "faster_csv" require "fileutils" class ParseletCSVStore include FileUtils SUFFIX = "skivvies.csv" def initialize(options = {}) @options = options @handles = {} @path = options[:store_path] || "." mkdir_p @path @keys = Dir[File.join(@path, "*.#{SUFFIX}")].inject({}) do |memo, path| max = 0 File.open(path, "r").each do |line| id = line.to_i max = id if id > max end memo[path] = max memo end @parselets = (options[:parselets] || []).map do |path| Parsley.new(File.read(path), options) end raise "no parselets provided" if @parselets.empty? end def put(key, tmpfile) path = tmpfile.path data = @parselets.map do |parselet| parselet.parse(options.merge(:file => path)) end visit(data, "root") rescue => e STDERR.puts e.message STDERR.puts e.backtrace.join("\n") end def close @handles.values.map{|h| h.close} @handles = {} end private def visit(data, key, base = nil, base_id = nil) if data.is_a?(Array) data.each do |entry| visit entry, key end return end raise "WTF: #{data.inspect}" unless data.is_a?(Hash) row = [] data.each do |k, v| if v.is_a?(String) row << v elsif v.is_a?(Array) && v.first.is_a?(String) row << v.join("|") else visit(v, k) end end unless row.empty? row.unshift(key) row.unshift(@keys[key] += 1) handle(key) << row end end def handle(key) @handles[key] ||= FasterCSV.open(File.join(@path, "#{key}.#{SUFFIX}"), "a") end def max(key) @keys[key] || 0 end end