gcal4ruby 0.2.11 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +5 -0
- data/lib/gcal4ruby/calendar.rb +15 -13
- data/lib/gcal4ruby/event.rb +41 -29
- data/lib/gcal4ruby/recurrence.rb +61 -12
- data/lib/gcal4ruby/service.rb +7 -3
- data/test/unit.rb +39 -0
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
#=CHANGELOG
|
2
|
+
#==version 0.3.0
|
3
|
+
#* Rewrote Event.find to improve performance significantly.
|
4
|
+
#* Added improvements to event recurrence handling, including loading existing recurrences, changing recurring events to non recurring and vice versa.
|
5
|
+
#* Added support for initialization attributes to Event, Calendar, Service and Recurrence.
|
6
|
+
#* Fixed query string typo in Event.find. Fix provided by nat.lownes.
|
2
7
|
#==version 0.2.11
|
3
8
|
#* Added support for GML elements in calendar events. Fix provided by nat.lownes.
|
4
9
|
#* Fixed event status bug where cancelled events were marked confirmed. Fix provided by rifraf.
|
data/lib/gcal4ruby/calendar.rb
CHANGED
@@ -116,24 +116,26 @@ class Calendar
|
|
116
116
|
#end
|
117
117
|
end
|
118
118
|
|
119
|
-
#Accepts a Service object. Returns the new Calendar
|
120
|
-
#error.
|
121
|
-
def initialize(service)
|
119
|
+
#Accepts a Service object and an optional attributes hash for initialization. Returns the new Calendar
|
120
|
+
#if successful, otherwise raises the InvalidService error.
|
121
|
+
def initialize(service, attributes = {})
|
122
122
|
super()
|
123
123
|
if !service.is_a?(Service)
|
124
124
|
raise InvalidService
|
125
125
|
end
|
126
|
-
|
127
|
-
|
126
|
+
attributes.each do |key, value|
|
127
|
+
self.send("#{key}=", value)
|
128
|
+
end
|
129
|
+
@xml ||= CALENDAR_XML
|
130
|
+
@service ||= service
|
128
131
|
@exists = false
|
129
|
-
@title
|
130
|
-
@summary
|
131
|
-
@public
|
132
|
-
@
|
133
|
-
@
|
134
|
-
@
|
135
|
-
@
|
136
|
-
@where = ""
|
132
|
+
@title ||= ""
|
133
|
+
@summary ||= ""
|
134
|
+
@public ||= false
|
135
|
+
@hidden ||= false
|
136
|
+
@timezone ||= "America/Los_Angeles"
|
137
|
+
@color ||= "#2952A3"
|
138
|
+
@where ||= ""
|
137
139
|
return true
|
138
140
|
end
|
139
141
|
|
data/lib/gcal4ruby/event.rb
CHANGED
@@ -115,8 +115,8 @@ module GCal4Ruby
|
|
115
115
|
#Sets the event's recurrence information to a Recurrence object. Returns the recurrence if successful,
|
116
116
|
#false otherwise
|
117
117
|
def recurrence=(r)
|
118
|
-
if r.is_a?(Recurrence)
|
119
|
-
r.event = self
|
118
|
+
if r.is_a?(Recurrence) or r.nil?
|
119
|
+
r.event = self unless r.nil?
|
120
120
|
@recurrence = r
|
121
121
|
else
|
122
122
|
return false
|
@@ -178,24 +178,21 @@ module GCal4Ruby
|
|
178
178
|
end
|
179
179
|
end
|
180
180
|
|
181
|
-
#Creates a new Event. Accepts a valid Calendar object.
|
182
|
-
def initialize(calendar)
|
181
|
+
#Creates a new Event. Accepts a valid Calendar object and optional attributes hash.
|
182
|
+
def initialize(calendar, attributes = {})
|
183
183
|
if not calendar.editable
|
184
184
|
raise CalendarNotEditable
|
185
185
|
end
|
186
186
|
super()
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
@
|
191
|
-
@
|
192
|
-
@
|
193
|
-
@
|
194
|
-
@
|
195
|
-
@
|
196
|
-
@attendees = []
|
197
|
-
@reminder = nil
|
198
|
-
@all_day = false
|
187
|
+
attributes.each do |key, value|
|
188
|
+
self.send("#{key}=", value)
|
189
|
+
end
|
190
|
+
@xml ||= EVENT_XML
|
191
|
+
@calendar ||= calendar
|
192
|
+
@transparency ||= "http://schemas.google.com/g/2005#event.opaque"
|
193
|
+
@status ||= "http://schemas.google.com/g/2005#event.confirmed"
|
194
|
+
@attendees ||= []
|
195
|
+
@all_day ||= false
|
199
196
|
end
|
200
197
|
|
201
198
|
#If the event does not exist on the Google Calendar service, save creates it. Otherwise
|
@@ -268,6 +265,19 @@ module GCal4Ruby
|
|
268
265
|
end
|
269
266
|
when "where"
|
270
267
|
ele.attributes["valueString"] = @where
|
268
|
+
when "recurrence"
|
269
|
+
puts 'recurrence element found' if @calendar.service.debug
|
270
|
+
if @recurrence
|
271
|
+
puts 'setting recurrence' if @calendar.service.debug
|
272
|
+
ele.text = @recurrence.to_s
|
273
|
+
else
|
274
|
+
puts 'no recurrence, adding when' if @calendar.service.debug
|
275
|
+
w = xml.root.add_element("gd:when")
|
276
|
+
xml.root.delete_element("/entry/gd:recurrence")
|
277
|
+
w.attributes["startTime"] = @all_day ? @start.strftime("%Y-%m-%d") : @start.xmlschema
|
278
|
+
w.attributes["endTime"] = @all_day ? @end.strftime("%Y-%m-%d") : @end.xmlschema
|
279
|
+
set_reminder(w)
|
280
|
+
end
|
271
281
|
end
|
272
282
|
end
|
273
283
|
if not @attendees.empty?
|
@@ -332,6 +342,8 @@ module GCal4Ruby
|
|
332
342
|
when "http://schemas.google.com/g/2005#event.cancelled"
|
333
343
|
@status = :cancelled
|
334
344
|
end
|
345
|
+
when 'recurrence'
|
346
|
+
@recurrence = Recurrence.new(ele.text)
|
335
347
|
when "transparency"
|
336
348
|
case ele.attributes["value"]
|
337
349
|
when "http://schemas.google.com/g/2005#event.transparent"
|
@@ -380,18 +392,18 @@ module GCal4Ruby
|
|
380
392
|
|
381
393
|
if test
|
382
394
|
puts "id passed, finding event by id" if calendar.service.debug
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
+
#ugly, but Google doesn't return the self url as ID as described in the API reference http://code.google.com/apis/calendar/data/2.0/developers_guide_protocol.html#RetrievingEvents
|
396
|
+
event_id = query.gsub("http://www.google.com/calendar/feeds/#{CGI::escape(calendar.service.account)}/events/",
|
397
|
+
"http://www.google.com/calendar/feeds/#{CGI::escape(calendar.service.account)}/private/full/")
|
398
|
+
es = calendar.service.send_get(event_id)
|
399
|
+
puts es.inspect if calendar.service.debug
|
400
|
+
if es
|
401
|
+
entry = REXML::Document.new(es.read_body).root
|
402
|
+
puts 'event found' if calendar.service.debug
|
403
|
+
Event.define_xml_namespaces(entry)
|
404
|
+
event = Event.new(calendar)
|
405
|
+
event.load("<?xml version='1.0' encoding='UTF-8'?>#{entry.to_s}")
|
406
|
+
return event
|
395
407
|
end
|
396
408
|
return nil
|
397
409
|
end
|
@@ -420,7 +432,7 @@ module GCal4Ruby
|
|
420
432
|
query_string += "&max-results=#{max_results}" if max_results
|
421
433
|
query_string += "&sortorder=#{sort_order}" if sort_order
|
422
434
|
query_string += "&ctz=#{timezone.gsub(" ", "_")}" if timezone
|
423
|
-
query_string += "&singleevents
|
435
|
+
query_string += "&singleevents=#{single_events}" if single_events
|
424
436
|
if query_string
|
425
437
|
events = calendar.service.send_get("http://www.google.com/calendar/feeds/#{calendar.id}/private/full?"+query_string)
|
426
438
|
ret = []
|
data/lib/gcal4ruby/recurrence.rb
CHANGED
@@ -3,6 +3,11 @@ class Time
|
|
3
3
|
def complete
|
4
4
|
self.utc.strftime("%Y%m%dT%H%M%S")
|
5
5
|
end
|
6
|
+
|
7
|
+
def self.parse_complete(value)
|
8
|
+
d, h = value.split("T")
|
9
|
+
return Time.parse(d+" "+h.gsub("Z", ""))
|
10
|
+
end
|
6
11
|
end
|
7
12
|
|
8
13
|
module GCal4Ruby
|
@@ -22,15 +27,59 @@ module GCal4Ruby
|
|
22
27
|
#True if the event is all day (i.e. no start/end time)
|
23
28
|
attr_accessor :all_day
|
24
29
|
|
25
|
-
#Returns a new Recurrence object
|
26
|
-
def initialize
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
#Accepts an optional attributes hash or a string containing a properly formatted ISO 8601 recurrence rule. Returns a new Recurrence object
|
31
|
+
def initialize(vars = {})
|
32
|
+
if vars.is_a? Hash
|
33
|
+
vars.each do |key, value|
|
34
|
+
self.send("#{key}=", value)
|
35
|
+
end
|
36
|
+
elsif vars.is_a? String
|
37
|
+
self.load(vars)
|
38
|
+
end
|
39
|
+
@all_day ||= false
|
40
|
+
end
|
41
|
+
|
42
|
+
#Accepts a string containing a properly formatted ISO 8601 recurrence rule and loads it into the recurrence object
|
43
|
+
def load(rec)
|
44
|
+
attrs = rec.split("\n")
|
45
|
+
attrs.each do |val|
|
46
|
+
key, value = val.split(":")
|
47
|
+
case key
|
48
|
+
when 'DTSTART'
|
49
|
+
@start = Time.parse_complete(value)
|
50
|
+
when 'DTSTART;VALUE=DATE'
|
51
|
+
@start = Time.parse(value)
|
52
|
+
@all_day = true
|
53
|
+
when 'DTSTART;VALUE=DATE-TIME'
|
54
|
+
@start = Time.parse_complete(value)
|
55
|
+
when 'DTEND'
|
56
|
+
@end = Time.parse_complete(value)
|
57
|
+
when 'DTEND;VALUE=DATE'
|
58
|
+
@end = Time.parse(value)
|
59
|
+
when 'DTEND;VALUE=DATE-TIME'
|
60
|
+
@end = Time.parse_complete(value)
|
61
|
+
when 'RRULE'
|
62
|
+
vals = value.split(";")
|
63
|
+
key = ''
|
64
|
+
by = ''
|
65
|
+
int = nil
|
66
|
+
vals.each do |rr|
|
67
|
+
a, h = rr.split("=")
|
68
|
+
case a
|
69
|
+
when 'FREQ'
|
70
|
+
key = h.downcase.capitalize
|
71
|
+
when 'INTERVAL'
|
72
|
+
int = h
|
73
|
+
when 'UNTIL'
|
74
|
+
@repeat_until = Time.parse(value)
|
75
|
+
else
|
76
|
+
by = h.split(",")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
@frequency = {key => by}
|
80
|
+
@frequency.merge({'interval' => int}) if int
|
81
|
+
end
|
82
|
+
end
|
34
83
|
end
|
35
84
|
|
36
85
|
#Returns a string with the correctly formatted ISO 8601 recurrence rule
|
@@ -75,7 +124,7 @@ module GCal4Ruby
|
|
75
124
|
when "monthly"
|
76
125
|
by += "BYDAY=#{value};"
|
77
126
|
when "yearly"
|
78
|
-
by += "BYYEARDAY=#{value}"
|
127
|
+
by += "BYYEARDAY=#{value};"
|
79
128
|
when 'interval'
|
80
129
|
i += "INTERVAL=#{value};"
|
81
130
|
end
|
@@ -83,7 +132,7 @@ module GCal4Ruby
|
|
83
132
|
output += f+i+by
|
84
133
|
end
|
85
134
|
if @repeat_until
|
86
|
-
output += "
|
135
|
+
output += "UNTIL=#{@repeat_until.strftime("%Y%m%d")}"
|
87
136
|
end
|
88
137
|
|
89
138
|
output += "\n"
|
@@ -136,7 +185,7 @@ module GCal4Ruby
|
|
136
185
|
#- *Monthly*: A value of a positive or negative integer (i.e. +1) prepended to a day-of-week string ('TU') to indicate the position of the day within the month. E.g. +1TU would be the first tuesday of the month.
|
137
186
|
#- *Yearly*: A value of 1 to 366 indicating the day of the year. May be negative to indicate counting down from the last day of the year.
|
138
187
|
#
|
139
|
-
#Optionally, you may specific a second hash pair to set the
|
188
|
+
#Optionally, you may specific a second hash pair to set the interval the event repeats:
|
140
189
|
# "interval" => '2'
|
141
190
|
#If the interval is missing, it is assumed to be 1.
|
142
191
|
#
|
data/lib/gcal4ruby/service.rb
CHANGED
@@ -29,9 +29,13 @@ class Service < Base
|
|
29
29
|
# adequate permissions
|
30
30
|
attr_accessor :check_public
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
#Accepts an optional attributes hash for initialization values
|
33
|
+
def initialize(attributes = {})
|
34
|
+
super()
|
35
|
+
attributes.each do |key, value|
|
36
|
+
self.send("#{key}=", value)
|
37
|
+
end
|
38
|
+
@check_public ||= true
|
35
39
|
end
|
36
40
|
|
37
41
|
# The authenticate method passes the username and password to google servers.
|
data/test/unit.rb
CHANGED
@@ -23,6 +23,7 @@ def tester
|
|
23
23
|
service_test
|
24
24
|
calendar_test
|
25
25
|
event_test
|
26
|
+
event_recurrence_test
|
26
27
|
end
|
27
28
|
|
28
29
|
def service_test
|
@@ -127,6 +128,44 @@ def event_test
|
|
127
128
|
end
|
128
129
|
end
|
129
130
|
|
131
|
+
def event_recurrence_test
|
132
|
+
puts "---Starting Event Recurrence Test---"
|
133
|
+
|
134
|
+
@first_start = Time.now
|
135
|
+
@first_end = Time.now+3600
|
136
|
+
@first_freq = {'weekly' => ['TU']}
|
137
|
+
@second_start = Time.now+86000
|
138
|
+
@second_end = Time.now+89600
|
139
|
+
@second_freq = {'weekly' => ['SA']}
|
140
|
+
|
141
|
+
puts "1. Create Recurring Event"
|
142
|
+
event = Event.new(@service.calendars[0])
|
143
|
+
event.title = "Test Recurring Event"
|
144
|
+
event.content = "Test event content"
|
145
|
+
event.recurrence = Recurrence.new({:start => @first_start, :end => @first_end, :frequency => @first_freq})
|
146
|
+
if event.save
|
147
|
+
successful event.to_xml
|
148
|
+
else
|
149
|
+
failed("recurrence = "+event.recurrence.to_s)
|
150
|
+
end
|
151
|
+
|
152
|
+
puts "2. Edit Recurrence"
|
153
|
+
event.title = "Edited recurring title"
|
154
|
+
event.recurrence = Recurrence.new({:start => @second_start, :end => @second_end, :frequency => @second_freq})
|
155
|
+
if event.save
|
156
|
+
successful event.to_xml
|
157
|
+
else
|
158
|
+
failed
|
159
|
+
end
|
160
|
+
|
161
|
+
puts "3. Delete Event"
|
162
|
+
if event.delete
|
163
|
+
successful
|
164
|
+
else
|
165
|
+
failed
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
130
169
|
def failed(m = nil)
|
131
170
|
puts "Test Failed"
|
132
171
|
puts m if m
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gcal4ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Reich
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-25 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|