Class: TimeSheet::Time::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/time_sheet/time/parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(dirs) ⇒ Parser

Returns a new instance of Parser.



7
8
9
# File 'lib/time_sheet/time/parser.rb', line 7

def initialize(dirs)
  @dirs = dirs
end

Instance Method Details

#entriesObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/time_sheet/time/parser.rb', line 23

def entries
  @entries ||= begin
    results = []
    hashes_per_file.each do |hashes|
      file_results = []
      hashes.each do |e|
        te = TimeSheet::Time::Entry.new(e)
        if file_results.last 
          file_results.last.next = te
          te.prev = file_results.last
        end
        file_results << te
      end
      results += file_results
    end
    results.sort!
    results.each do |r|
      unless r.valid?
        raise r.exception, [
          r.exception.message, ': ',
          r.data.inspect,
          ', preceeding entry: ',
          r.prev
        ].join
      end
    end
    results
  end
end

#filesObject



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/time_sheet/time/parser.rb', line 11

def files
  results = []
  @dirs.each do |dir|
    if File.directory?(dir)
      results += Dir["#{dir}/**/*.xlsx"]
    else
      results << dir
    end
  end
  results.sort
end

#hashes_per_fileObject



53
54
55
56
57
58
59
60
61
62
63
# File 'lib/time_sheet/time/parser.rb', line 53

def hashes_per_file
  @hashes_per_file ||= begin
    files.map do |f|
      if f.match(/https:\/\/docs\.google\.com/)
        parse_google_doc(f)
      else
        parse_xlsx(f)
      end
    end
  end
end

#nullify_empties(record) ⇒ Object



114
115
116
117
118
# File 'lib/time_sheet/time/parser.rb', line 114

def nullify_empties(record)
  record.transform_values do |v|
    v == '' ? nil : v
  end
end

#parse_date_and_time(record) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/time_sheet/time/parser.rb', line 101

def parse_date_and_time(record)
  record.merge(
    'date' => (record['date'] ? Date.parse(record['date']) : nil),
    'start' => (record['start'] ? DateTime.parse(record['start']) : nil),
    'end' => (record['end'] ? DateTime.parse(record['end']) : nil)
  )
rescue ArgumentError => e
  binding.pry if TimeSheet.options[:debug]
  puts "current record: #{record.inspect}"
  return {}
  # raise e
end

#parse_google_doc(url) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/time_sheet/time/parser.rb', line 84

def parse_google_doc(url)
  # Chart Tools datasource protocol, see 
  # https://developers.google.com/chart/interactive/docs/querylanguage
  response = HTTPClient.get(url)

  if response.status == 200
    data = CSV.parse(response.body, liberal_parsing: true)
    headers = data.shift
    data.map do |row|
      record = nullify_empties(headers.zip(row).to_h)
      parse_date_and_time(record)
    end
  else
    raise "request to google docs failed (#{response.status}):\n#{response.body}"
  end
end

#parse_xlsx(filename) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/time_sheet/time/parser.rb', line 65

def parse_xlsx(filename)
  results = []

  xlsx = Roo::Spreadsheet.open(filename)
  xlsx.each_with_pagename do |name, sheet|
    headers = sheet.row(1).to_h{|e| [e, e]}
    rows = sheet.parse(headers)

    rows.each do |row|
      next unless row['start']
      next if row.values.all?{|v| [nil, ''].include?(v)}

      results << row
    end
  end

  results
end