Class: Timelog::Book::Entries

Inherits:
Object
  • Object
show all
Defined in:
lib/timelog/book/entries.rb

Constant Summary collapse

QUERY_REGEX =
/\A\d+|all|archived|non\-archived|active|today\Z/

Instance Method Summary collapse

Constructor Details

#initialize(book) ⇒ Entries

Returns a new instance of Entries.



6
7
8
# File 'lib/timelog/book/entries.rb', line 6

def initialize(book)
  @book = book
end

Instance Method Details

#activeObject

get the active entry

returns the currently active entry or nil if none was found



71
72
73
# File 'lib/timelog/book/entries.rb', line 71

def active
  where("active").first
end

#active_or_newObject

get the active or a new entry

this can be an already started entry or a fresh nonstarted entry if an ongoing entry was not found



63
64
65
# File 'lib/timelog/book/entries.rb', line 63

def active_or_new
  active || Entry.new
end

#archive(entry, options = {}) ⇒ Object

archives the entry



51
52
53
54
55
56
# File 'lib/timelog/book/entries.rb', line 51

def archive(entry, options = {})
  @book.trigger :before, :archive, entry
  entry.archived = true
  write entry
  @book.trigger :after, :archive, entry
end

#pause(entry, options = {}) ⇒ Object

pauses an entry

Raises:

  • (EntryNotActiveError)


11
12
13
14
15
16
17
18
19
# File 'lib/timelog/book/entries.rb', line 11

def pause(entry, options = {})
  raise EntryNotActiveError unless entry.active?
  raise EntryPausedError if entry.paused?
  raise EntryNotStarted unless entry.started?
  @book.trigger :before, :pause, entry
  entry.pause options[:at]
  write entry
  @book.trigger :after, :pause, entry
end

#read(id) ⇒ Object

get entries from ids

fetches and loads all entries with the given ids returns an array with entries sorted by id desc



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/timelog/book/entries.rb', line 100

def read(id)
  id = [id] unless id.is_a? Array
  @book.database.execute("select * from entries where id in (#{id.compact.map {"?"}.join(", ")}) order by id", id.compact).map do |row|
    entry = Entry.new
    entry.id = row[0]
    entry.client = row[1]
    entry.project = row[2]
    entry.description = row[3]
    entry.started = Time.at(row[4]) if row[4]
    entry.stopped = Time.at(row[5]) if row[5]
    if row[6] and pauses = Marshal.load(row[6])
      pauses.each {|pause, resume| entry.pause(pause); entry.resume(resume)}
    end
    entry.archived = (row[7] == 1) ? true : false
    entry
  end
end

#resume(entry, options = {}) ⇒ Object

resumes an entry

Raises:

  • (EntryNotActiveError)


22
23
24
25
26
27
28
29
# File 'lib/timelog/book/entries.rb', line 22

def resume(entry, options = {})
  raise EntryNotActiveError unless entry.active?
  raise EntryNotPausedError unless entry.paused?
  @book.trigger :before, :resume, entry
  entry.resume options[:at]
  write entry
  @book.trigger :after, :resume, entry
end

#start(entry, options = {}) ⇒ Object

starts an entry

Raises:

  • (EntryStartedError)


32
33
34
35
36
37
38
# File 'lib/timelog/book/entries.rb', line 32

def start(entry, options = {})
  raise EntryStartedError if entry.started?
  @book.trigger :before, :start, entry
  entry.started = options[:at] || Time.now
  write entry
  @book.trigger :after, :start, entry
end

#stop(entry, options = {}) ⇒ Object

ends the entry

Raises:

  • (EntryNotStartedError)


41
42
43
44
45
46
47
48
# File 'lib/timelog/book/entries.rb', line 41

def stop(entry, options = {})
  raise EntryNotStartedError unless entry.started?
  @book.trigger :before, :stop, entry
  entry.resume(options[:at] || Time.now) if entry.paused?
  entry.stopped = options[:at] || Time.now
  write entry
  @book.trigger :after, :stop, entry
end

#where(query) ⇒ Object

find entries from query

get a list of entries, based on the query provided

Raises:

  • (InvalidQueryError)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/timelog/book/entries.rb', line 78

def where(query)
  raise InvalidQueryError if query !~ QUERY_REGEX    
  bind = []
  where = case query.to_s
  when /\A\d+\Z/
    bind << query
    "where id = ?"
  when "all" then ""
  when "active" then "where stopped is null"
  when "archived" then "where archived = 1"
  when "non-archived" then "where archived = 0"
  when "today"
    bind += [Date.today.to_time.to_i, Date.today.to_time.to_i + 24 * 60 * 60]
    "where started > ? and started < ?"
  end
  read(@book.database.first_column("select id from entries #{where} order by id", *bind))
end

#write(entry) ⇒ Object

write a single entry to book

persists an entry to the database automatically sets the id on the entry if it is a new entry



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/timelog/book/entries.rb', line 123

def write(entry)
  if entry.valid?
    data = [
      entry.client,
      entry.project,
      entry.description,
      entry.started.try(:to_i),
      entry.stopped.try(:to_i),
      Marshal.dump(entry.pauses),
      entry.archived ? 1 : 0
    ]
    if entry.id
      @book.database.execute("update entries set
        client = ?, project = ?, description = ?, 
        started = ?, stopped = ?, pauses = ?,
        archived = ? where id = ?", data << entry.id)
    else
      @book.database.execute("insert into entries
        (client, project, description, started, stopped, pauses, archived) 
        values(?, ?, ?, ?, ?, ?, ?)", data)
      entry.id = @book.database.first_value("select id from entries order by id desc limit 1")
    end
  else
    raise InvalidEntryError
  end
end