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

978307200
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 }
VERSION =
'2.1.0'

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.



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

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



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

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



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
# File 'lib/icalPal.rb', line 35

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}")

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

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

  end

  return(rows)
end

.nth(n, dow, m) ⇒ RDT

Get the n‘th dow in month m

Parameters:

  • n (Integer)

    Integer between -4 and +4

  • dow (String)

    Day of the week abbreviation from ICalPal::DOW

  • m (RDT)

    The RDT with the year and month we’re searching

Returns:

  • (RDT)

    The resulting day



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/icalPal.rb', line 147

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 i.wday == DOW[dow.to_sym]
    return i if j == n
  end
end

Instance Method Details

#[](k) ⇒ Object



172
# File 'lib/icalPal.rb', line 172

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

#[]=(k, v) ⇒ Object



173
# File 'lib/icalPal.rb', line 173

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

#initialize(obj) ⇒ Object

Parameters:

  • obj (ICalPal)

    A Store or Calendar



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/icalPal.rb', line 73

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



174
# File 'lib/icalPal.rb', line 174

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



91
92
93
94
95
96
# File 'lib/icalPal.rb', line 91

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>.



102
103
104
105
106
107
# File 'lib/icalPal.rb', line 102

def to_xml
  retval = ""
  @self.keys.each { |k| retval += xmlify(k, @self[k]) }

  retval
end

#valuesObject



175
# File 'lib/icalPal.rb', line 175

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



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/icalPal.rb', line 115

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

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

  # Array
  when Array then
    # Treat empty arrays as nil values
    return(xmlify(key, nil)) if value[0] == nil 

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

  # RDT
  when ICalPal::RDT then return("<#{key}>#{value.to_s}</#{key}>")

  # Unknown
  else return("<#{key}>#{value.to_s}</#{key}>")
  end
end