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.
@@ -0,0 +1,273 @@
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
+
19
+ class Time
20
+ #Returns a ISO 8601 complete formatted string of the time
21
+ def complete
22
+ self.utc.strftime("%Y%m%dT%H%M%S")
23
+ end
24
+
25
+ def self.parse_complete(value)
26
+ d, h = value.split("T")
27
+ return Time.parse(d+" "+h.gsub("Z", ""))
28
+ end
29
+ end
30
+
31
+ module GCal4Ruby
32
+ #The Recurrence class stores information on an Event's recurrence. The class implements
33
+ #the RFC 2445 iCalendar recurrence description.
34
+ class Recurrence
35
+ #The event start date/time
36
+ attr_reader :start_time
37
+ #The event end date/time
38
+ attr_reader :end_time
39
+ #the event reference
40
+ attr_reader :event
41
+ #The date until which the event will be repeated
42
+ attr_reader :repeat_until
43
+ #The event frequency
44
+ attr_reader :frequency
45
+ #True if the event is all day (i.e. no start/end time)
46
+ attr_accessor :all_day
47
+
48
+ #Accepts an optional attributes hash or a string containing a properly formatted ISO 8601 recurrence rule. Returns a new Recurrence object
49
+ def initialize(vars = {})
50
+ if vars.is_a? Hash
51
+ vars.each do |key, value|
52
+ self.send("#{key}=", value)
53
+ end
54
+ elsif vars.is_a? String
55
+ self.load(vars)
56
+ end
57
+ @all_day ||= false
58
+ end
59
+
60
+ #Accepts a string containing a properly formatted ISO 8601 recurrence rule and loads it into the recurrence object
61
+ def load(rec)
62
+ attrs = rec.split("\n")
63
+ attrs.each do |val|
64
+ key, value = val.split(":")
65
+ case key
66
+ when 'DTSTART'
67
+ @start_time = Time.parse_complete(value)
68
+ when 'DTSTART;VALUE=DATE'
69
+ @start_time = Time.parse(value)
70
+ @all_day = true
71
+ when 'DTSTART;VALUE=DATE-TIME'
72
+ @start_time = Time.parse_complete(value)
73
+ when 'DTEND'
74
+ @end_time = Time.parse_complete(value)
75
+ when 'DTEND;VALUE=DATE'
76
+ @end_time = Time.parse(value)
77
+ when 'DTEND;VALUE=DATE-TIME'
78
+ @end_time = Time.parse_complete(value)
79
+ when 'RRULE'
80
+ vals = value.split(";")
81
+ key = ''
82
+ by = ''
83
+ int = nil
84
+ vals.each do |rr|
85
+ a, h = rr.split("=")
86
+ case a
87
+ when 'FREQ'
88
+ key = h.downcase.capitalize
89
+ when 'INTERVAL'
90
+ int = h
91
+ when 'UNTIL'
92
+ @repeat_until = Time.parse(value)
93
+ else
94
+ by = h.split(",")
95
+ end
96
+ end
97
+ @frequency = {key => by}
98
+ @frequency.merge({'interval' => int}) if int
99
+ end
100
+ end
101
+ end
102
+
103
+ def to_s
104
+ output = ''
105
+ if @frequency
106
+ f = ''
107
+ i = ''
108
+ by = ''
109
+ @frequency.each do |key, v|
110
+ if v.is_a?(Array)
111
+ if v.size > 0
112
+ value = v.join(",")
113
+ else
114
+ value = nil
115
+ end
116
+ else
117
+ value = v
118
+ end
119
+ f += "#{key.downcase} " if key != 'interval'
120
+ case key.downcase
121
+ when "secondly"
122
+ by += "every #{value} second"
123
+ when "minutely"
124
+ by += "every #{value} minute"
125
+ when "hourly"
126
+ by += "every #{value} hour"
127
+ when "weekly"
128
+ by += "on #{value}" if value
129
+ when "monthly"
130
+ by += "on #{value}"
131
+ when "yearly"
132
+ by += "on the #{value} day of the year"
133
+ when 'interval'
134
+ i += "for #{value} times"
135
+ end
136
+ end
137
+ output += f+i+by
138
+ end
139
+ if @repeat_until
140
+ output += " and repeats until #{@repeat_until.strftime("%m/%d/%Y")}"
141
+ end
142
+ output
143
+ end
144
+
145
+ #Returns a string with the correctly formatted ISO 8601 recurrence rule
146
+ def to_recurrence_string
147
+
148
+ output = ''
149
+ if @all_day
150
+ output += "DTSTART;VALUE=DATE:#{@start_time.utc.strftime("%Y%m%d")}\n"
151
+ else
152
+ output += "DTSTART;VALUE=DATE-TIME:#{@start_time.complete}\n"
153
+ end
154
+ if @all_day
155
+ output += "DTEND;VALUE=DATE:#{@end_time.utc.strftime("%Y%m%d")}\n"
156
+ else
157
+ output += "DTEND;VALUE=DATE-TIME:#{@end_time.complete}\n"
158
+ end
159
+ output += "RRULE:"
160
+ if @frequency
161
+ f = 'FREQ='
162
+ i = ''
163
+ by = ''
164
+ @frequency.each do |key, v|
165
+ if v.is_a?(Array)
166
+ if v.size > 0
167
+ value = v.join(",")
168
+ else
169
+ value = nil
170
+ end
171
+ else
172
+ value = v
173
+ end
174
+ f += "#{key.upcase};" if key != 'interval'
175
+ case key.downcase
176
+ when "secondly"
177
+ by += "BYSECOND=#{value};"
178
+ when "minutely"
179
+ by += "BYMINUTE=#{value};"
180
+ when "hourly"
181
+ by += "BYHOUR=#{value};"
182
+ when "weekly"
183
+ by += "BYDAY=#{value};" if value
184
+ when "monthly"
185
+ by += "BYDAY=#{value};"
186
+ when "yearly"
187
+ by += "BYYEARDAY=#{value};"
188
+ when 'interval'
189
+ i += "INTERVAL=#{value};"
190
+ end
191
+ end
192
+ output += f+i+by
193
+ end
194
+ if @repeat_until
195
+ output += "UNTIL=#{@repeat_until.strftime("%Y%m%d")}"
196
+ end
197
+
198
+ output += "\n"
199
+ end
200
+
201
+ #Sets the start date/time. Must be a Time object.
202
+ def start_time=(s)
203
+ if not s.is_a?(Time)
204
+ raise RecurrenceValueError, "Start must be a date or a time"
205
+ else
206
+ @start_time = s
207
+ end
208
+ end
209
+
210
+ #Sets the end Date/Time. Must be a Time object.
211
+ def end_time=(e)
212
+ if not e.is_a?(Time)
213
+ raise RecurrenceValueError, "End must be a date or a time"
214
+ else
215
+ @end_time = e
216
+ end
217
+ end
218
+
219
+ #Sets the parent event reference
220
+ def event=(e)
221
+ if not e.is_a?(Event)
222
+ raise RecurrenceValueError, "Event must be an event"
223
+ else
224
+ @event = e
225
+ end
226
+ end
227
+
228
+ #Sets the end date for the recurrence
229
+ def repeat_until=(r)
230
+ if not r.is_a?(Date)
231
+ raise RecurrenceValueError, "Repeat_until must be a date"
232
+ else
233
+ @repeat_until = r
234
+ end
235
+ end
236
+
237
+ #Sets the frequency of the recurrence. Should be a hash with one of
238
+ #"SECONDLY", "MINUTELY", "HOURLY", "DAILY", "WEEKLY", "MONTHLY", "YEARLY" as the key,
239
+ #and as the value, an array containing zero to n of the following:
240
+ #- *Secondly*: A value between 0 and 59. Causes the event to repeat on that second of each minut.
241
+ #- *Minutely*: A value between 0 and 59. Causes the event to repeat on that minute of every hour.
242
+ #- *Hourly*: A value between 0 and 23. Causes the even to repeat on that hour of every day.
243
+ #- *Daily*: No value needed - will cause the event to repeat every day until the repeat_until date.
244
+ #- *Weekly*: A value of the first two letters of a day of the week. Causes the event to repeat on that day.
245
+ #- *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.
246
+ #- *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.
247
+ #
248
+ #Optionally, you may specific a second hash pair to set the interval the event repeats:
249
+ # "interval" => '2'
250
+ #If the interval is missing, it is assumed to be 1.
251
+ #
252
+ #===Examples
253
+ #Repeat event every Tuesday:
254
+ # frequency = {"Weekly" => ["TU"]}
255
+ #
256
+ #Repeat every first and third Monday of the month
257
+ # frequency = {"Monthly" => ["+1MO", "+3MO"]}
258
+ #
259
+ #Repeat on the last day of every year
260
+ # frequency = {"Yearly" => [366]}
261
+ #
262
+ #Repeat every other week on Friday
263
+ # frequency = {"Weekly" => ["FR"], "interval" => "2"}
264
+
265
+ def frequency=(f)
266
+ if f.is_a?(Hash)
267
+ @frequency = f
268
+ else
269
+ raise RecurrenceValueError, "Frequency must be a hash (see documentation)"
270
+ end
271
+ end
272
+ end
273
+ end
@@ -0,0 +1,160 @@
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'
19
+ require 'gdata4ruby/gdata_object'
20
+ require 'gdata4ruby/utils/utils'
21
+ require 'gdata4ruby/acl/access_rule'
22
+ require 'gcal4ruby/calendar'
23
+ require 'gcal4ruby/event'
24
+ require 'gcal4ruby/recurrence'
25
+ require 'rexml/document'
26
+
27
+ module GCal4Ruby
28
+ #The service class is the main handler for all direct interactions with the
29
+ #Google Calendar API. A service represents a single user account. Each user
30
+ #account can have multiple calendars, so you'll need to find the calendar you
31
+ #want from the service, using the Calendar#find class method.
32
+ #=Usage
33
+ #
34
+ #1. Authenticate
35
+ # service = Service.new
36
+ # service.authenticate("user@gmail.com", "password")
37
+ #
38
+ #2. Get Calendar List
39
+ # calendars = service.calendars
40
+ #
41
+ class Service < GData4Ruby::Service
42
+ CALENDAR_LIST_FEED = 'http://www.google.com/calendar/feeds/default/allcalendars/full'
43
+
44
+ #Convenience attribute contains the currently authenticated account name
45
+ attr_reader :account
46
+
47
+ # The token returned by the Google servers, used to authorize all subsequent messages
48
+ attr_reader :auth_token
49
+
50
+ # Determines whether GCal4Ruby ensures a calendar is public. Setting this to false can increase speeds by
51
+ # 50% but can cause errors if you try to do something to a calendar that is not public and you don't have
52
+ # adequate permissions
53
+ attr_accessor :check_public
54
+
55
+ #Accepts an optional attributes hash for initialization values
56
+ def initialize(attributes = {})
57
+ super(attributes)
58
+ attributes.each do |key, value|
59
+ self.send("#{key}=", value)
60
+ end
61
+ @check_public ||= true
62
+ end
63
+
64
+ def default_event_feed
65
+ return "http://www.google.com/calendar/feeds/#{@account}/private/full"
66
+ end
67
+
68
+ # The authenticate method passes the username and password to google servers.
69
+ # If authentication succeeds, returns true, otherwise raises the AuthenticationFailed error.
70
+ def authenticate(username, password, service='cl')
71
+ super(username, password, service)
72
+ end
73
+
74
+ #Helper function to reauthenticate to a new Google service without having to re-set credentials.
75
+ def reauthenticate(service='cl')
76
+ authenticate(@account, @password, service)
77
+ end
78
+
79
+ #Returns an array of Calendar objects for each calendar associated with
80
+ #the authenticated account.
81
+ def calendars
82
+ if not @auth_token
83
+ raise NotAuthenticated
84
+ end
85
+ ret = send_request(GData4Ruby::Request.new(:get, CALENDAR_LIST_FEED, nil, {"max-results" => "10000"}))
86
+ cals = []
87
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
88
+ entry = GData4Ruby::Utils.add_namespaces(entry)
89
+ cal = Calendar.new(self)
90
+ cal.load(entry.to_s)
91
+ cals << cal
92
+ end
93
+ return cals
94
+ end
95
+
96
+ #Returns an array of Event objects for each event in this account
97
+ def events
98
+ if not @auth_token
99
+ raise NotAuthenticated
100
+ end
101
+ ret = send_request(GData4Ruby::Request.new(:get, default_event_feed, nil, {"max-results" => "10000"}))
102
+ events = []
103
+ REXML::Document.new(ret.body).root.elements.each("entry"){}.map do |entry|
104
+ entry = GData4Ruby::Utils.add_namespaces(entry)
105
+ event = Event.new(self)
106
+ event.load(entry.to_s)
107
+ events << event
108
+ end
109
+ return events
110
+ end
111
+
112
+ #Helper function to return a formatted iframe embedded google calendar. Parameters are:
113
+ #1. *cals*: either an array of calendar ids, or <em>:all</em> for all calendars, or <em>:first</em> for the first (usally default) calendar
114
+ #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:
115
+ # height:: the height of the embedded calendar in pixels
116
+ # width:: the width of the embedded calendar in pixels
117
+ # title:: the title to display
118
+ # bgcolor:: the background color. Limited choices, see google docs for allowable values.
119
+ # showTitle:: set to '0' to hide the title
120
+ # showDate:: set to '0' to hide the current date
121
+ # showNav:: set to '0 to hide the navigation tools
122
+ # showPrint:: set to '0' to hide the print icon
123
+ # showTabs:: set to '0' to hide the tabs
124
+ # showCalendars:: set to '0' to hide the calendars selection drop down
125
+ # showTz:: set to '0' to hide the timezone selection
126
+ # border:: the border width in pixels
127
+ # dates:: a range of dates to display in the format of 'yyyymmdd/yyyymmdd'. Example: 20090820/20091001
128
+ # privateKey:: use to display a private calendar. You can find this key under the calendar settings pane of the Google Calendar website.
129
+ # ctz:: The timezone to convert event times to
130
+ #3. *colors*: a hash of calendar ids as key and color values as associated hash values. Example: {'test@gmail.com' => '#7A367A'}
131
+ def to_iframe(cals, params = {}, colors = {})
132
+ params[:height] ||= "600"
133
+ params[:width] ||= "600"
134
+ params[:title] ||= (self.account ? self.account : '')
135
+ params[:bgcolor] ||= "#FFFFFF"
136
+ params[:border] ||= "0"
137
+ params.each{|key, value| params[key] = CGI::escape(value)}
138
+ output = "#{params.to_a.collect{|a| a.join("=")}.join("&")}&"
139
+
140
+ if cals.is_a?(Array)
141
+ for c in cals
142
+ output += "src=#{c}&"
143
+ if colors and colors[c]
144
+ output += "color=%23#{colors[c].gsub("#", "")}&"
145
+ end
146
+ end
147
+ elsif cals == :all
148
+ cal_list = calendars()
149
+ for c in cal_list
150
+ output += "src=#{c.id}&"
151
+ end
152
+ elsif cals == :first
153
+ cal_list = calendars()
154
+ output += "src=#{cal_list[0].id}&"
155
+ end
156
+
157
+ "<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>"
158
+ end
159
+ end
160
+ end
data/lib/gcal4ruby.rb ADDED
@@ -0,0 +1 @@
1
+ require "gcal4ruby/service"
data/test/unit.rb ADDED
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'rubygems'
4
+ require 'gcal4ruby'
5
+ include GCal4Ruby
6
+
7
+ @service = Service.new
8
+ @username = nil
9
+ @password = nil
10
+
11
+ def tester
12
+ if ARGV.include?("-d")
13
+ @service.debug = true
14
+ end
15
+ ARGV.each do |ar|
16
+ if ar.match("username=")
17
+ @username = ar.gsub("username=", "")
18
+ end
19
+ if ar.match("password=")
20
+ @password = ar.gsub("password=", "")
21
+ end
22
+ end
23
+ service_test
24
+ calendar_test
25
+ event_test
26
+ event_recurrence_test
27
+ end
28
+
29
+ def service_test
30
+ puts "---Starting Service Test---"
31
+ puts "1. Authenticate"
32
+ if @service.authenticate(@username, @password)
33
+ successful
34
+ else
35
+ failed
36
+ end
37
+
38
+ puts "2. Calendar List"
39
+ cals = @service.calendars
40
+ if cals
41
+ successful "Calendars for this Account:"
42
+ cals.each do |cal|
43
+ puts cal.title
44
+ end
45
+ else
46
+ failed
47
+ end
48
+ end
49
+
50
+ def calendar_test
51
+ puts "---Starting Calendar Test---"
52
+
53
+ puts "1. Create Calendar"
54
+ cal = Calendar.new(@service)
55
+ cal.title = "test calendar"+Time.now.to_s
56
+ puts "Calender exists = "+cal.exists?.to_s
57
+ if cal.save
58
+ successful cal.to_xml
59
+ else
60
+ failed
61
+ end
62
+
63
+ puts "2. Edit Calendar"
64
+ cal.title = "renamed title"
65
+ if cal.save
66
+ successful cal.to_xml
67
+ else
68
+ puts "Test 2 Failed"
69
+ end
70
+
71
+ puts "3. Find Calendar by ID"
72
+ c = Calendar.find(@service, {:id => cal.id})
73
+ if c.title == cal.title
74
+ successful
75
+ else
76
+ failed "#{c.title} not equal to #{cal.title}"
77
+ end
78
+
79
+ puts "4. Delete Calendar"
80
+ if cal.delete and not cal.exists?
81
+ successful
82
+ else
83
+ failed
84
+ end
85
+ end
86
+
87
+ def event_test
88
+ puts "---Starting Event Test---"
89
+
90
+ puts "1. Create Event"
91
+ event = Event.new(@service)
92
+ event.calendar = @service.calendars[0]
93
+ event.title = "Test Event"
94
+ event.content = "Test event content"
95
+ event.start_time = Time.now+1800
96
+ event.end_time = Time.now+5400
97
+ if event.save
98
+ successful event.to_xml
99
+ else
100
+ failed
101
+ end
102
+
103
+ puts "2. Edit Event"
104
+ event.title = "Edited title"
105
+ if event.save
106
+ successful event.to_xml
107
+ else
108
+ failed
109
+ end
110
+
111
+ puts "3. Reload Event"
112
+ if event.reload
113
+ successful
114
+ end
115
+
116
+ puts "4. Find Event by id"
117
+ e = Event.find(@service, {:id => event.id})
118
+ if e.title == event.title
119
+ successful
120
+ else
121
+ failed "Found event doesn't match existing event"
122
+ end
123
+
124
+ puts "5. Delete Event"
125
+ if event.delete
126
+ successful
127
+ else
128
+ failed
129
+ end
130
+ end
131
+
132
+ def event_recurrence_test
133
+ puts "---Starting Event Recurrence Test---"
134
+
135
+ @first_start = Time.now
136
+ @first_end = Time.now+3600
137
+ @first_freq = {'weekly' => ['TU']}
138
+ @second_start = Time.now+86000
139
+ @second_end = Time.now+89600
140
+ @second_freq = {'weekly' => ['SA']}
141
+
142
+ puts "1. Create Recurring Event"
143
+ event = Event.new(@service)
144
+ event.calendar = @service.calendars[0]
145
+ event.title = "Test Recurring Event"
146
+ event.content = "Test event content"
147
+ event.recurrence = Recurrence.new({:start_time => @first_start, :end_time => @first_end, :frequency => @first_freq})
148
+ if event.save
149
+ successful event.to_xml
150
+ else
151
+ failed("recurrence = "+event.recurrence.to_s)
152
+ end
153
+
154
+ puts "2. Edit Recurrence"
155
+ event.title = "Edited recurring title"
156
+ event.recurrence = Recurrence.new({:start_time => @second_start, :end_time => @second_end, :frequency => @second_freq})
157
+ if event.save
158
+ successful event.to_xml
159
+ else
160
+ failed
161
+ end
162
+
163
+ puts "3. Delete Event"
164
+ if event.delete
165
+ successful
166
+ else
167
+ failed
168
+ end
169
+ end
170
+
171
+ def failed(m = nil)
172
+ puts "Test Failed"
173
+ puts m if m
174
+ exit()
175
+ end
176
+
177
+ def successful(m = nil)
178
+ puts "Test Successful"
179
+ puts m if m
180
+ end
181
+
182
+ tester
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: railsware-gcal4ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 1
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 5
10
+ version: 0.5.5
11
+ platform: ruby
12
+ authors:
13
+ - Mike Reich
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-08 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: gdata4ruby
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 25
30
+ segments:
31
+ - 0
32
+ - 1
33
+ - 1
34
+ version: 0.1.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: "GCal4Ruby is a Ruby Gem that can be used to interact with the current version of the Google Calendar API. GCal4Ruby provides the following features: Create and edit calendar events, Add and invite users to events, Set reminders, Make recurring events."
38
+ email: mike@seabourneconsulting.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - README
47
+ - CHANGELOG
48
+ - lib/gcal4ruby.rb
49
+ - lib/gcal4ruby/service.rb
50
+ - lib/gcal4ruby/calendar.rb
51
+ - lib/gcal4ruby/event.rb
52
+ - lib/gcal4ruby/recurrence.rb
53
+ - test/unit.rb
54
+ has_rdoc: true
55
+ homepage: http://cookingandcoding.com/gcal4ruby/
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project: gcal4ruby
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: A full featured wrapper for interacting with the Google Calendar API
88
+ test_files:
89
+ - test/unit.rb