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 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.
@@ -116,24 +116,26 @@ class Calendar
116
116
  #end
117
117
  end
118
118
 
119
- #Accepts a Service object. Returns the new Calendar if successful, otherwise raises the InvalidService
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
- @xml = CALENDAR_XML
127
- @service = service
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 = false
132
- @id = nil
133
- @hidden = false
134
- @timezone = "America/Los_Angeles"
135
- @color = "#2952A3"
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
 
@@ -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
- @xml = EVENT_XML
188
- @calendar = calendar
189
- @title = nil
190
- @content = nil
191
- @start = nil
192
- @end = nil
193
- @where = nil
194
- @transparency = "http://schemas.google.com/g/2005#event.opaque"
195
- @status = "http://schemas.google.com/g/2005#event.confirmed"
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
- es = calendar.service.send_get("http://www.google.com/calendar/feeds/#{calendar.id}/private/full?max-results=1000000")
384
- REXML::Document.new(es.read_body).root.elements.each("entry"){}.map do |entry|
385
- puts "element = "+entry.name if calendar.service.debug
386
- id = ''
387
- entry.elements.each("id") {|v| id = v.text}
388
- puts "id = #{id}" if calendar.service.debug
389
- if id == query
390
- Event.define_xml_namespaces(entry)
391
- event = Event.new(calendar)
392
- event.load("<?xml version='1.0' encoding='UTF-8'?>#{entry.to_s}")
393
- return event
394
- end
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#{single_events}" if single_events
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 = []
@@ -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
- @start = nil
28
- @end = nil
29
- @event = nil
30
- @day_of_week = nil
31
- @repeat_until = nil
32
- @frequency = nil
33
- @all_day = false
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 += ";UNTIL=#{@repeat_until.strftime("%Y%m%d")}"
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 internal the even repeats:
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
  #
@@ -29,9 +29,13 @@ class Service < Base
29
29
  # adequate permissions
30
30
  attr_accessor :check_public
31
31
 
32
- def initialize
33
- super
34
- @check_public = true
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.2.11
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-23 00:00:00 +11:00
12
+ date: 2010-01-25 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies: []
15
15