railsware-gcal4ruby 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG ADDED
@@ -0,0 +1,80 @@
1
+ #=CHANGELOG
2
+ #==version 0.5.5
3
+ #* Fixed calendar :find
4
+ #==version 0.5.4
5
+ #* Fixed Service#to_iframe bgcolor bug
6
+ #==version 0.5.3
7
+ #* Fixed bug when loading event attributes when initializing
8
+ #==version 0.5.2
9
+ #* Fixed calendar.public functionality for making calendars publicly viewable.
10
+ #* Fixed to_iframe output methods
11
+ #* Fixed issue with creating new events
12
+ #==version 0.5.1
13
+ #* Minor fixes to to_iframe methods
14
+ #==version 0.5.0 - MAJOR CHANGES
15
+ #* Now using GData4Ruby library as base class for service, calendar, and event objects. This removed the base.rb class, which is now inherited from
16
+ # GData4ruby
17
+ #* Added 'events' method to service to get all events for an account.
18
+ #* Major interface changes to find methods - these are not backwards compatible changes.
19
+ #* Changed Event#find default behavior to search all calendars.
20
+ #* Major interface changes to to_iframe methods - these are not backwards compatible changes.
21
+ #* Added support for multiple reminders.
22
+ #* Improved object relationship for events. Events are now service-centric, i.e. events are instantiated with a service object.
23
+ #* Event calendar is now set through a 'calendar' attribute.
24
+ #* Fixes to event recurrence handling and display.
25
+ #* Added support for reminders with recurring events.
26
+ #* Numerous improvements to performance.
27
+ #* Calendar objects no longer have to query ACL feed to determine editability.
28
+ #* Added support for event statuses: cancelled, tentative or confirmed.
29
+ #==version 0.3.2
30
+ #* Updated the Event.find method to support finding all events by passing :all as the query term.
31
+ #==version 0.3.1
32
+ #* Fixed Event.find method to work with secondary calendars and google apps accounts. Fix provided by groesser3.
33
+ #* Added max results to Calendar.find.
34
+ #==version 0.3.0
35
+ #* Rewrote Event.find to improve performance significantly.
36
+ #* Added improvements to event recurrence handling, including loading existing recurrences, changing recurring events to non recurring and vice versa.
37
+ #* Added support for initialization attributes to Event, Calendar, Service and Recurrence.
38
+ #* Fixed query string typo in Event.find. Fix provided by nat.lownes.
39
+ #==version 0.2.11
40
+ #* Added support for GML elements in calendar events. Fix provided by nat.lownes.
41
+ #* Fixed event status bug where cancelled events were marked confirmed. Fix provided by rifraf.
42
+ #==version 0.2.10
43
+ #* Fixed library support for Google Hosted Apps accounts running in forced SSL mode.
44
+ #==version 0.2.9
45
+ #* Fixed small SSL redirect bug due to variable misnaming in base.rb. Fix provided by JohnMetta
46
+ #==version 0.2.8
47
+ #* Merged changes from edruder and h13ronim from the unofficial github repo - http://github.com/h13ronim/gcal4ruby/commits/master
48
+ #==version 0.2.7
49
+ #* Added fix for finding events in calendars that have more than 25 entries
50
+ #==version 0.2.6
51
+ #* Added fix for updated google calendar XML per http://cookingandcoding.wordpress.com/2009/06/08/new-ruby-google-calendar-api-gem-gcal4ruby/#comment-183
52
+ #==version 0.2.5
53
+ #* Added calendar color support to to_iframe methods in Calendar and Service.
54
+ #==version 0.2.4
55
+ #* Fixed bug with ACL check in Calendar#load
56
+ #==version 0.2.3
57
+ #* Implemented to_iframe method for calendars and services to output embeddable iframe text.
58
+ #* Added switch to turn off ACL check for public calendars. Can increase effeciency if turned off.
59
+ #==version 0.2.2
60
+ #* Fixed URL encoding problem in Event.find method.
61
+ #* cleaned up Event.find method to allow for finding events by id
62
+ #* updated Calendar.find method to add params hash
63
+ #* added 'published', 'updated', and 'edited' attributes
64
+ #==version 0.2.1
65
+ #* fixed Event.find calendar specification
66
+ #==version 0.2.0
67
+ #* Fixed redirect URI query params problem
68
+ #* Updated syntax for finding events to include most google api parameters, Non-backwards compatible.
69
+ #==version 0.1.4
70
+ #* Added additional search criteria for Event.find
71
+ #==version 0.1.3
72
+ #* Added support for authenticating with Google Hosted Apps accounts
73
+ #* Added flag to indicate whether a calendar is editable
74
+ #* Added handling to gracefully throw error when trying to create event on a non-editable (shared) calendar
75
+ #==version 0.1.2
76
+ #* Fixed to_xml dump problem with hidden and selected attributes
77
+ #==version 0.1.1
78
+ #* Added all_day indicator to event to indicate an all day event
79
+ #==version 0.1.0
80
+ #* Initial Version
data/README ADDED
@@ -0,0 +1,97 @@
1
+ #=GCal4Ruby
2
+ #
3
+ #==Introduction
4
+ #GCal4Ruby is a full featured wrapper for the google calendar API. GCal4Ruby implements
5
+ #all of the functionality available through the Google Calnedar API, including permissions,
6
+ #attendees, reminders and event recurrence.
7
+ #
8
+ #==Author and Contact Information
9
+ #GCal4Ruby was created and is maintained by {Mike Reich}[mailto:mike@seabourneconsulting.com]
10
+ #and is licenses under the GPL v2. Feel free to use and update, but be sure to contribute your
11
+ #code back to the project and attribute as required by the license.
12
+ #===Website
13
+ #http://cookingandcoding.com/gcal4ruby/
14
+ #
15
+ #==Description
16
+ #GCal4Ruby has three major components: the service, calendar and event objects. Each service
17
+ #has many calendars, which in turn have many events. Each service is the representation of a
18
+ #google account, and thus must be successfully authenticated using valid Google Calendar
19
+ #account credentials.
20
+ #
21
+ #==Examples
22
+ #Below are some common usage examples. For more examples, check the documentation.
23
+ #===Service
24
+ #1. Authenticate
25
+ # service = Service.new
26
+ # service.authenticate("user@gmail.com", "password")
27
+ #
28
+ #2. Get Calendar List
29
+ # calendars = service.calendars
30
+ #
31
+ #===Calendar
32
+ #All usages assume a successfully authenticated Service.
33
+ #1. Create a new Calendar
34
+ # cal = Calendar.new(service)
35
+ #
36
+ #2. Find a calendar by ID
37
+ # cal = Calendar.find(service, {:id => cal_id})
38
+ #
39
+ #3. Get all calendar events
40
+ # cal = Calendar.find(service, {:id => cal_id})
41
+ # events = cal.events
42
+ #
43
+ #4. Find an existing calendar by title
44
+ # cal = Calendar.find(service, {:title => "New Calendar"})
45
+ #
46
+ #5. Find all calendars containing a search term
47
+ # cal = Calendar.find(service, "Soccer Team")
48
+ #===Event
49
+ #All usages assume a successfully authenticated Service and valid Calendar.
50
+ #1. Create a new Event
51
+ # event = Event.new(service, {:calendar => cal, :title => "Soccer Game", :start => Time.parse("12-06-2009 at 12:30 PM"), :end => Time.parse("12-06-2009 at 1:30 PM"), :where => "Merry Playfields"})
52
+ # event.save
53
+ #
54
+ #2. Find an existing Event by title
55
+ # event = Event.find(service, {:title => "Soccer Game"})
56
+ #
57
+ #3. Find an existing Event by ID
58
+ # event = Event.find(service, {:id => event.id})
59
+ #
60
+ #4. Find all events containing the search term
61
+ # event = Event.find(service, "Soccer Game")
62
+ #
63
+ #5. Find all events on a calendar containing the search term
64
+ # event = Event.find(service, "Soccer Game", {:calendar => cal.id})
65
+ #
66
+ #6. Find events within a date range
67
+ # event = Event.find(service, "Soccer Game", {'start-min' => Time.parse("01/01/2010").utc.xmlschema, 'start-max' => Time.parse("06/01/2010").utc.xmlschema})
68
+ #
69
+ #7. Create a recurring event for every saturday
70
+ # event = Event.new(service)
71
+ # event.title = "Baseball Game"
72
+ # event.calendar = cal
73
+ # event.where = "Municipal Stadium"
74
+ # event.recurrence = Recurrence.new
75
+ # event.recurrence.start_time = Time.parse("06/20/2009 at 4:30 PM")
76
+ # event.recurrence.end_time = Time.parse("06/20/2009 at 6:30 PM")
77
+ # event.recurrence.frequency = {"weekly" => ["SA"]}
78
+ # event.save
79
+ #
80
+ #8. Create an event with a 15 minute email reminder
81
+ # event = Event.new(service)
82
+ # event.calendar = cal
83
+ # event.title = "Dinner with Kate"
84
+ # event.start_time = Time.parse("06/20/2009 at 5 pm")
85
+ # event.end_time = Time.parse("06/20/2009 at 8 pm")
86
+ # event.where = "Luigi's"
87
+ # event.reminder = {:minutes => 15, :method => 'email'}
88
+ # event.save
89
+ #
90
+ #9. Create an event with attendees
91
+ # event = Event.new(service)
92
+ # event.calendar = cal
93
+ # event.title = "Dinner with Kate"
94
+ # event.start_time = Time.parse("06/20/2009 at 5 pm")
95
+ # event.end_time = Time.parse("06/20/2009 at 8 pm")
96
+ # event.attendees => {:name => "Kate", :email => "kate@gmail.com"}
97
+ # event.save
@@ -0,0 +1,366 @@
1
+ # Author:: Mike Reich (mike@seabourneconsulting.com)
2
+ # Copyright:: Copyright (C) 2010 Mike Reich
3
+ # License:: GPL v2
4
+ #--
5
+ # Licensed under the General Public License (GPL), Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ #
15
+ # Feel free to use and update, but be sure to contribute your
16
+ # code back to the project and attribute as required by the license.
17
+ #++
18
+ require 'gdata4ruby/acl/access_rule'
19
+ module GCal4Ruby
20
+ #The Calendar Class is the representation of a Google Calendar. Each user account
21
+ #can have multiple calendars. You must have an authenticated Service object before
22
+ #using the Calendar object.
23
+ #=Usage
24
+ #All usages assume a successfully authenticated Service.
25
+ #1. Create a new Calendar
26
+ # cal = Calendar.new(service)
27
+ #
28
+ #2. Find a calendar by ID
29
+ # cal = Calendar.find(service, {:id => cal_id})
30
+ #
31
+ #3. Get all calendar events
32
+ # cal = Calendar.find(service, {:id => cal_id})
33
+ # events = cal.events
34
+ #
35
+ #4. Find an existing calendar by title
36
+ # cal = Calendar.find(service, {:title => "New Calendar"})
37
+ #
38
+ #5. Find all calendars containing a search term
39
+ # cal = Calendar.find(service, "Soccer Team")
40
+ #
41
+ #After a calendar object has been created or loaded, you can change any of the
42
+ #attributes like you would any other object. Be sure to save the calendar to write changes
43
+ #to the Google Calendar service.
44
+ class Calendar < GData4Ruby::GDataObject
45
+ CALENDAR_FEED = "http://www.google.com/calendar/feeds/default/owncalendars/full/"
46
+ CALENDAR_QUERY_FEED = "http://www.google.com/calendar/feeds/default/calendars/"
47
+ CALENDAR_XML = "<entry xmlns='http://www.w3.org/2005/Atom'
48
+ xmlns:gd='http://schemas.google.com/g/2005'
49
+ xmlns:gCal='http://schemas.google.com/gCal/2005'>
50
+ <title type='text'></title>
51
+ <summary type='text'></summary>
52
+ <gCal:timezone value='America/Los_Angeles'></gCal:timezone>
53
+ <gCal:hidden value='false'></gCal:hidden>
54
+ <gCal:color value='#2952A3'></gCal:color>
55
+ <gd:where rel='' label='' valueString='Oakland'></gd:where>
56
+ </entry>"
57
+
58
+ #A short description of the calendar
59
+ attr_accessor :summary
60
+
61
+ #Boolean value indicating the calendar visibility
62
+ attr_accessor :hidden
63
+
64
+ #The calendar timezone[http://code.google.com/apis/calendar/docs/2.0/reference.html#gCaltimezone]
65
+ attr_accessor :timezone
66
+
67
+ #The calendar color. Must be one of these[http://code.google.com/apis/calendar/docs/2.0/reference.html#gCalcolor] values.
68
+ attr_accessor :color
69
+
70
+ #The calendar geo location, if any
71
+ attr_accessor :where
72
+
73
+ #A boolean value indicating whether the calendar appears by default when viewed online
74
+ attr_accessor :selected
75
+
76
+ #A flag indicating whether the calendar is editable by this account
77
+ attr_reader :editable
78
+
79
+ #Accepts a Service object and an optional attributes hash for initialization. Returns the new Calendar
80
+ #if successful, otherwise raises the InvalidService error.
81
+ def initialize(service, attributes = {})
82
+ super(service, attributes)
83
+ if !service.is_a?(Service)
84
+ raise InvalidService
85
+ end
86
+ @xml = CALENDAR_XML
87
+ @service ||= service
88
+ @exists = false
89
+ @title ||= ""
90
+ @summary ||= ""
91
+ @public ||= false
92
+ @hidden ||= false
93
+ @timezone ||= "America/Los_Angeles"
94
+ @color ||= "#2952A3"
95
+ @where ||= ""
96
+ attributes.each do |key, value|
97
+ self.send("#{key}=", value)
98
+ end
99
+ return true
100
+ end
101
+
102
+ #Returns true if the calendar exists on the Google Calendar system (i.e. was
103
+ #loaded or has been saved). Otherwise returns false.
104
+ def exists?
105
+ return @exists
106
+ end
107
+
108
+ #Returns true if the calendar is publically accessable, otherwise returns false.
109
+ def public?
110
+ return @public
111
+ end
112
+
113
+ #Returns an array of Event objects corresponding to each event in the calendar.
114
+ def events
115
+ events = []
116
+ ret = @service.send_request(GData4Ruby::Request.new(:get, @content_uri))
117
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
118
+ entry = GData4Ruby::Utils.add_namespaces(entry)
119
+ e = Event.new(service)
120
+ if e.load(entry.to_s)
121
+ events << e
122
+ end
123
+ end
124
+ return events
125
+ end
126
+
127
+
128
+ #Saves the calendar.
129
+ def save
130
+ public = @public
131
+ ret = super
132
+ return ret if public == @public
133
+ if public
134
+ puts 'setting calendar to public' if service.debug
135
+ rule = GData4Ruby::ACL::AccessRule.new(service, self)
136
+ rule.role = 'http://schemas.google.com/gCal/2005#read'
137
+ rule.save
138
+ else
139
+ rule = GData4Ruby::ACL::AccessRule.find(service, self, {:user => 'default'})
140
+ rule.delete if rule
141
+ end
142
+ reload
143
+ end
144
+
145
+ #Set the calendar to public (p = true) or private (p = false). Publically viewable
146
+ #calendars can be accessed by anyone without having to log in to google calendar. See
147
+ #Calendar#to_iframe on how to display a public calendar in a webpage.
148
+ def public=(p)
149
+ @public = p
150
+ end
151
+
152
+ #Creates a new instance of the object
153
+ def create
154
+ return service.send_request(GData4Ruby::Request.new(:post, CALENDAR_FEED, to_xml()))
155
+ end
156
+
157
+ #Finds a Calendar based on a text query or by an id. Parameters are:
158
+ #*service*:: A valid Service object to search.
159
+ #*query*:: either a string containing a text query to search by, or a hash containing an +id+ key with an associated id to find, or a +query+ key containint a text query to search for, or a +title+ key containing a title to search.
160
+ #*args*:: a hash containing optional additional query paramters to use. See http://code.google.com/apis/gdata/docs/2.0/reference.html#Queries for a full list of possible values. Example:
161
+ # {'max-results' => '100'}
162
+ #If an ID is specified, a single instance of the calendar is returned if found, otherwise false.
163
+ #If a query term or title text is specified, and array of matching results is returned, or an empty array if nothing
164
+ #was found.
165
+ def self.find(service, query, args = {})
166
+ raise ArgumentError, 'query must be a hash or string' if not query.is_a? Hash and not query.is_a? String
167
+ if query.is_a? Hash and query[:id]
168
+ id = query[:id]
169
+ puts "id passed, finding calendar by id" if service.debug
170
+ puts "id = "+id if service.debug
171
+ d = service.send_request(GData4Ruby::Request.new(:get, CALENDAR_FEED+id, {"If-Not-Match" => "*"}))
172
+ puts d.inspect if service.debug
173
+ if d
174
+ return get_instance(service, d)
175
+ end
176
+ else
177
+ #fugly, but Google doesn't provide a way to query the calendar feed directly
178
+ old_public = service.check_public
179
+ service.check_public = false
180
+ results = []
181
+ cals = service.calendars
182
+ cals.each do |cal|
183
+ if query.is_a?(Hash)
184
+ results << cal if query[:query] and cal.title.downcase.include? query[:query].downcase
185
+ results << cal if query[:title] and cal.title == query[:title]
186
+ else
187
+ results << cal if cal.title.downcase.include? query.downcase
188
+ end
189
+ end
190
+ service.check_public = old_public
191
+ return results
192
+ end
193
+ return false
194
+ end
195
+
196
+ #Reloads the calendar objects information from the stored server version. Returns true
197
+ #if successful, otherwise returns false. Any information not saved will be overwritten.
198
+ def reload
199
+ return false if not @exists
200
+ t = Calendar.find(service, {:id => @id})
201
+ if t
202
+ load(t.to_xml)
203
+ else
204
+ return false
205
+ end
206
+ end
207
+
208
+ #Returns the xml representation of the Calenar.
209
+ def to_xml
210
+ xml = REXML::Document.new(super)
211
+ xml.root.elements.each(){}.map do |ele|
212
+ case ele.name
213
+ when "summary"
214
+ ele.text = @summary
215
+ when "timezone"
216
+ ele.attributes["value"] = @timezone
217
+ when "hidden"
218
+ ele.attributes["value"] = @hidden.to_s
219
+ when "color"
220
+ ele.attributes["value"] = @color
221
+ when "selected"
222
+ ele.attributes["value"] = @selected.to_s
223
+ end
224
+ end
225
+ xml.to_s
226
+ end
227
+
228
+ #Loads the Calendar with returned data from Google Calendar feed. Returns true if successful.
229
+ def load(string)
230
+ super(string)
231
+ @exists = true
232
+ @xml = string
233
+ xml = REXML::Document.new(string)
234
+ xml.root.elements.each(){}.map do |ele|
235
+ case ele.name
236
+ when "id"
237
+ @id = ele.text.gsub("http://www.google.com/calendar/feeds/default/calendars/", "")
238
+ when 'summary'
239
+ @summary = ele.text
240
+ when "color"
241
+ @color = ele.attributes['value']
242
+ when 'hidden'
243
+ @hidden = ele.attributes["value"] == "true" ? true : false
244
+ when 'timezone'
245
+ @timezone = ele.attributes["value"]
246
+ when "selected"
247
+ @selected = ele.attributes["value"] == "true" ? true : false
248
+ when "link"
249
+ if ele.attributes['rel'] == 'edit'
250
+ @edit_feed = ele.attributes['href']
251
+ end
252
+ when 'accesslevel'
253
+ @editable = (ele.attributes["value"] == 'editor' or ele.attributes["value"] == 'owner' or ele.attributes["value"] == 'root')
254
+ end
255
+ end
256
+
257
+ if @service.check_public
258
+ puts "Getting ACL Feed" if @service.debug
259
+
260
+ #rescue error on shared calenar ACL list access
261
+ begin
262
+ ret = @service.send_request(GData4Ruby::Request.new(:get, @acl_uri))
263
+ rescue Exception => e
264
+ puts "ACL Feed Get Failed: #{e.inspect}" if @service.debug
265
+ @public = false
266
+ return true
267
+ end
268
+ r = REXML::Document.new(ret.read_body)
269
+ r.root.elements.each("entry") do |ele|
270
+ e = GData4Ruby::ACL::AccessRule.new(service, self)
271
+ ele = GData4Ruby::Utils.add_namespaces(ele)
272
+ e.load(ele.to_s)
273
+ puts 'acl rule = '+e.inspect if service.debug
274
+ @public = (e.role.include? 'read' and e.user == 'default')
275
+ puts 'public = '+@public.to_s if service.debug
276
+ break if @public
277
+ end
278
+ else
279
+ @public = false
280
+ end
281
+ return true
282
+ end
283
+
284
+ #Helper function to return a formatted iframe embedded google calendar. Parameters are:
285
+ #1. *params*: a hash of parameters that affect the display of the embedded calendar. Accepts any parameter that the google iframe recognizes. Here are the most common:
286
+ # height:: the height of the embedded calendar in pixels
287
+ # width:: the width of the embedded calendar in pixels
288
+ # title:: the title to display
289
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
290
+ # color:: the color of the calendar elements. Limited choices, see google docs for allowable values.
291
+ # showTitle:: set to '0' to hide the title
292
+ # showDate:: set to '0' to hide the current date
293
+ # showNav:: set to '0 to hide the navigation tools
294
+ # showPrint:: set to '0' to hide the print icon
295
+ # showTabs:: set to '0' to hide the tabs
296
+ # showCalendars:: set to '0' to hide the calendars selection drop down
297
+ # showTz:: set to '0' to hide the timezone selection
298
+ # border:: the border width in pixels
299
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
300
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
301
+ # ctz:: The timezone to convert event times to
302
+ def to_iframe(params = {})
303
+ params[:height] ||= "600"
304
+ params[:width] ||= "600"
305
+ params[:title] ||= (self.title ? self.title : '')
306
+ params[:bgcolor] ||= "#FFFFFF"
307
+ params[:color] ||= "#2952A3"
308
+ params[:border] ||= "0"
309
+ params.each{|key, value| params[key] = CGI::escape(value)}
310
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}"
311
+
312
+ output += "&src=#{id}"
313
+
314
+ "<iframe src='http://www.google.com/calendar/embed?#{output}' style='#{params[:border]} px solid;' width='#{params[:width]}' height='#{params[:height]}' frameborder='#{params[:border]}' scrolling='no'></iframe>"
315
+ end
316
+
317
+ #Helper function to return a specified calendar id as a formatted iframe embedded google calendar. This function does not require loading the calendar information from the Google calendar
318
+ #service, but does require you know the google calendar id.
319
+ #1. *id*: the unique google assigned id for the calendar to display.
320
+ #2. *params*: a hash of parameters that affect the display of the embedded calendar. Accepts any parameter that the google iframe recognizes. Here are the most common:
321
+ # height:: the height of the embedded calendar in pixels
322
+ # width:: the width of the embedded calendar in pixels
323
+ # title:: the title to display
324
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
325
+ # color:: the color of the calendar elements. Limited choices, see google docs for allowable values.
326
+ # showTitle:: set to '0' to hide the title
327
+ # showDate:: set to '0' to hide the current date
328
+ # showNav:: set to '0 to hide the navigation tools
329
+ # showPrint:: set to '0' to hide the print icon
330
+ # showTabs:: set to '0' to hide the tabs
331
+ # showCalendars:: set to '0' to hide the calendars selection drop down
332
+ # showTz:: set to '0' to hide the timezone selection
333
+ # border:: the border width in pixels
334
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
335
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
336
+ def self.to_iframe(id, params = {})
337
+ params[:height] ||= "600"
338
+ params[:width] ||= "600"
339
+ params[:bgcolor] ||= "#FFFFFF"
340
+ params[:color] ||= "#2952A3"
341
+ params[:border] ||= "0"
342
+ params.each{|key, value| params[key] = CGI::escape(value)}
343
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}"
344
+
345
+ output += "&src=#{id}"
346
+
347
+ "<iframe src='http://www.google.com/calendar/embed?#{output}' style='#{params[:border]} px solid;' width='#{params[:width]}' height='#{params[:height]}' frameborder='#{params[:border]}' scrolling='no'></iframe>"
348
+ end
349
+
350
+ private
351
+ def self.get_instance(service, d)
352
+ if d.is_a? Net::HTTPOK
353
+ xml = REXML::Document.new(d.read_body).root
354
+ if xml.name == 'feed'
355
+ xml = xml.elements.each("entry"){}[0]
356
+ end
357
+ else
358
+ xml = d
359
+ end
360
+ ele = GData4Ruby::Utils::add_namespaces(xml)
361
+ cal = Calendar.new(service)
362
+ cal.load(ele.to_s)
363
+ cal
364
+ end
365
+ end
366
+ end