Module: ICalPal

Included in:
Calendar, Event, Reminder, Store
Defined in:
lib/icalPal.rb,
lib/rdt.rb,
lib/event.rb,
lib/store.rb,
lib/options.rb,
lib/version.rb,
lib/calendar.rb,
lib/reminder.rb

Overview

Encapsulate the Store (accounts), Calendar and CalendarItem tables of a Calendar database, and the Reminder table of a Reminders database

Defined Under Namespace

Classes: Calendar, Event, Options, RDT, Reminder, Store

Constant Summary collapse

ITIME =

Epoch + 31 years

978_307_200
DOW =

Days of the week abbreviations used in recurrence rules

SU, MO, TU, WE, TH, FR, SA

{ 'SU': 0, 'MO': 1, 'TU': 2, 'WE': 3, 'TH': 4, 'FR': 5, 'SA': 6 }.freeze
NAME =
'icalPal'.freeze
VERSION =
'3.2.0'.freeze

Instance Attribute Summary collapse

Accessors collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#selfObject (readonly)

Returns the value of attribute self.



13
14
15
# File 'lib/icalPal.rb', line 13

def self
  @self
end

Class Method Details

.call(klass) ⇒ Class

Dynamic instantiation of our classes based on the command being run

Parameters:

  • klass (String)

    One of accounts, stores, calendars, events, or tasks

Returns:

  • (Class)

    The subclass of ICalPal



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/icalPal.rb', line 20

def self.call(klass)
  case klass
  when 'accounts' then Store
  when 'stores' then Store
  when 'calendars' then Calendar
  when 'events' then Event
  when 'tasks' then Reminder
  else
    $log.fatal("Unknown class: #{klass}")
    exit
  end
end

.load_data(db_file, q) ⇒ Object

Load data



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/icalPal.rb', line 34

def self.load_data(db_file, q)
  $log.debug(q.gsub(/\n/, ' '))

  rows = []

  begin
    # Open the database
    $log.debug("Opening database: #{db_file}")
    db = SQLite3::Database.new(db_file, { readonly: true, results_as_hash: true })

    # Prepare the query
    stmt = db.prepare(q)
    abort(stmt.columns.sort.join(' ')) if $opts[:props].any? 'list'
    $opts[:props] = stmt.columns - $opts[:eep] if $opts[:props].any? 'all'

    # Iterate the SQLite3::ResultSet once
    stmt.execute.each_with_index { |i, j| rows[j] = i }
    stmt.close

    # Close the database
    db.close
    $log.debug("Closed #{db_file}")

  rescue SQLite3::BusyException => e
    $log.error("Non-fatal error closing database #{db.filename}")
    raise e

  rescue SQLite3::CantOpenException => e
    $log.debug("Can't open #{db_file}")
    raise e

  rescue SQLite3::SQLException => e
    $log.info("#{db_file}: #{e}")
    raise e

  rescue SQLite3::Exception => e
    abort("#{db_file}: #{e}")
  end

  rows
end

.nth(n, dow, m) ⇒ RDT

Get the n‘th dow in month m

Parameters:

  • n (Integer)

    Integer between -4 and +4

  • dow (Array)

    Days of the week

  • m (RDT)

    The RDT with the year and month we’re searching

Returns:

  • (RDT)

    The resulting day



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/icalPal.rb', line 151

def self.nth(n, dow, m)
  # Get the number of days in the month
  a = [ ICalPal::RDT.new(m.year, m.month, 1) ] # First of this month
  a[1] = (a[0] >> 1) - 1                       # First of next month, minus 1 day

  # Reverse it if going backwards
  a.reverse! if n.negative?
  step = a[1] <=> a[0]

  j = 0
  a[0].step(a[1], step) do |i|
    j += step if dow.any?(i.wday)
    return i if j == n
  end
end

Instance Method Details

#[](k) ⇒ Object



176
177
178
# File 'lib/icalPal.rb', line 176

def [](k)
  @self[k]
end

#[]=(k, v) ⇒ Object



180
181
182
# File 'lib/icalPal.rb', line 180

def []=(k, v)
  @self[k] = v
end

#initialize(obj) ⇒ Object

Parameters:

  • obj (ICalPal)

    A Store or Calendar



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/icalPal.rb', line 77

def initialize(obj)
  obj['type'] = EventKit::EKSourceType.find_index { |i| i[:name] == 'Subscribed' } if obj['subcal_url']
  type = EventKit::EKSourceType[obj['type']]

  obj['store'] = obj['account']

  obj['type'] = type[:name]
  obj['color'] ||= type[:color]
  obj['symbolic_color_name'] ||= type[:color]

  @self = obj
end

#keysObject



184
185
186
# File 'lib/icalPal.rb', line 184

def keys
  @self.keys
end

#to_csv(headers) ⇒ CSV::Row

Create a new CSV::Row with values from self. Newlines are replaced with ‘n’ to ensure each Row is a single line of text.

Parameters:

  • headers (Array)

    Key names used as the header row in a CSV::Table

Returns:

  • (CSV::Row)

    The Store, Calendar, or CalendarItem as a CSV::Row



95
96
97
98
99
100
# File 'lib/icalPal.rb', line 95

def to_csv(headers)
  values = []
  headers.each { |h| values.push((@self[h].respond_to?(:gsub))? @self[h].gsub(/\n/, '\n') : @self[h]) }

  CSV::Row.new(headers, values)
end

#to_xmlString

Convert self to XML

Fields with empty values return <field/>.

Returns:

  • (String)

    All fields in a simple XML format: <field>value</field>.



106
107
108
109
110
111
# File 'lib/icalPal.rb', line 106

def to_xml
  retval = ''
  @self.each_key { |k| retval += xmlify(k, @self[k]) }

  retval
end

#valuesObject



188
189
190
# File 'lib/icalPal.rb', line 188

def values
  @self.values
end

#xmlify(key, value) ⇒ String

Convert a key/value pair to XML. The value should be nil, String, Integer, Array, or ICalPal::RDT

Parameters:

  • key

    The key

  • value

    The value

Returns:

  • (String)

    The key/value pair in a simple XML format



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/icalPal.rb', line 119

def xmlify(key, value)
  case value
  # Nil
  when NilClass then "<#{key}/>"

  # String, Integer
  when String then "<#{key}>#{value}</#{key}>"
  when Integer then "<#{key}>#{value}</#{key}>"

  # Array
  when Array
    # Treat empty arrays as nil values
    xmlify(key, nil) if value[0].nil?

    retval = ''
    value.each { |x| retval += xmlify("#{key}0", x) }
    "<#{key}>#{retval}</#{key}>"

  # RDT
  when ICalPal::RDT then "<#{key}>#{value}</#{key}>"

  # Unknown
  else "<#{key}>#{value}</#{key}>"
  end
end