gcal_mapper 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +32 -0
  2. data/.travis.yml +16 -0
  3. data/CHANGELOG.md +15 -0
  4. data/Gemfile +20 -0
  5. data/Guardfile +19 -0
  6. data/LICENSE +22 -0
  7. data/README.md +370 -0
  8. data/Rakefile +32 -0
  9. data/bin/ci/file/auth.yaml +7 -0
  10. data/bin/ci/file/bad_yaml.yaml +0 -0
  11. data/bin/ci/file/config.yaml +8 -0
  12. data/bin/ci/file/privatekey.p12 +0 -0
  13. data/bin/ci/travis_build.sh +4 -0
  14. data/bin/ci/vcr/GcalMapper_Authentification/access_token_should_exist_with_assertion_auth.yml +49 -0
  15. data/bin/ci/vcr/GcalMapper_Authentification/should_be_fasle_if_bad_client_email_is_given.yml +47 -0
  16. data/bin/ci/vcr/GcalMapper_Authentification_Assertion/should_have_access_token_attribute.yml +49 -0
  17. data/bin/ci/vcr/GcalMapper_Authentification_Assertion/should_have_refresh_token_attribute.yml +49 -0
  18. data/bin/ci/vcr/GcalMapper_Calendar/should_get_the_calendar_list.yml +190 -0
  19. data/bin/ci/vcr/GcalMapper_Calendar/should_get_the_events_list.yml +45 -0
  20. data/bin/ci/vcr/GcalMapper_Calendar/should_raise_error_if_the_calendar_id_isn_t_accessible.yml +56 -0
  21. data/bin/ci/vcr/GcalMapper_Calendar/should_raise_error_if_the_token_is_bad.yml +60 -0
  22. data/bin/ci/vcr/GcalMapper_Mapper/should_save_all_events.yml +232 -0
  23. data/bin/ci/vcr/GcalMapper_Mapper/should_save_events_only_once.yml +232 -0
  24. data/bin/gcal-mapper +108 -0
  25. data/gcal_mapper.gemspec +25 -0
  26. data/lib/gcal_mapper.rb +15 -0
  27. data/lib/gcal_mapper/authentification.rb +57 -0
  28. data/lib/gcal_mapper/authentification/assertion.rb +110 -0
  29. data/lib/gcal_mapper/authentification/base.rb +20 -0
  30. data/lib/gcal_mapper/authentification/oauth2.rb +68 -0
  31. data/lib/gcal_mapper/calendar.rb +51 -0
  32. data/lib/gcal_mapper/configuration.rb +23 -0
  33. data/lib/gcal_mapper/errors.rb +40 -0
  34. data/lib/gcal_mapper/mapper.rb +76 -0
  35. data/lib/gcal_mapper/mapper/active_record.rb +74 -0
  36. data/lib/gcal_mapper/mapper/dsl.rb +57 -0
  37. data/lib/gcal_mapper/mapper/simple.rb +97 -0
  38. data/lib/gcal_mapper/railtie.rb +8 -0
  39. data/lib/gcal_mapper/rest_request.rb +73 -0
  40. data/lib/gcal_mapper/sync.rb +159 -0
  41. data/lib/gcal_mapper/version.rb +4 -0
  42. data/spec/authentification/assertion_spec.rb +15 -0
  43. data/spec/authentification/base_spec.rb +18 -0
  44. data/spec/authentification/oauth2_spec.rb +15 -0
  45. data/spec/authentification_spec.rb +34 -0
  46. data/spec/calendar_spec.rb +33 -0
  47. data/spec/gcal_mapper_spec.rb +5 -0
  48. data/spec/mapper/active_record_spec.rb +46 -0
  49. data/spec/mapper/dsl_spec.rb +31 -0
  50. data/spec/mapper/simple_spec.rb +48 -0
  51. data/spec/mapper_spec.rb +32 -0
  52. data/spec/rest_request_spec.rb +5 -0
  53. data/spec/spec_helper.rb +51 -0
  54. data/spec/support/models/event.rb +25 -0
  55. data/spec/support/models/event_jeu.rb +22 -0
  56. data/spec/support/schema.rb +28 -0
  57. data/spec/sync_spec.rb +28 -0
  58. metadata +200 -0
data/.gitignore ADDED
@@ -0,0 +1,32 @@
1
+ *.gem
2
+ *.rbc
3
+ *.sqlite3
4
+ InstalledFiles
5
+ Gemfile.lock
6
+ pkg
7
+ lib/bundler/man
8
+ spec/reports
9
+ tmp
10
+
11
+ # ignore local config files
12
+ .bundle
13
+ .config
14
+ .rspec
15
+ .project
16
+
17
+ # ignore simplecov path
18
+ coverage
19
+
20
+ # ignore vcr files
21
+ spec/vcr
22
+ spec/vcr/**/*
23
+ spec/file
24
+
25
+ # YARD artifacts
26
+ .yardoc
27
+ _yardoc
28
+ doc
29
+ rdoc
30
+
31
+ # google api yaml file
32
+ google-api.yaml
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ branches:
3
+ only:
4
+ - master
5
+ rvm:
6
+ - 1.8.7
7
+ - 1.9.2
8
+ - 1.9.3
9
+
10
+ before_script:
11
+ - bin/ci/travis_build.sh
12
+
13
+ notifications:
14
+ recipients:
15
+ - neville.dubuis@liquid-concept.ch
16
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,15 @@
1
+ master
2
+ ======
3
+
4
+ 0.1.0 / 2012-06-06
5
+ ------------------
6
+ * map google events in your database
7
+ * use of regex to map only a part of the data
8
+ * is_empty declaration to use to look in another field is the source is empty
9
+ * map mutliple calendar at the same time
10
+ * DSL to simplify configuration
11
+ * extend "client" class with the synchronization method
12
+ * Oauth2.0 authentification
13
+ * Assertion credentials authentification
14
+ * Compatible with ActiveRecord
15
+ * Could work without ORM
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gcalmapper.gemspec
4
+ gemspec
5
+ gem 'guard-rspec'
6
+ gem 'guard-spork'
7
+ gem 'guard-bundler'
8
+ gem 'libnotify'
9
+ gem 'rb-readline'
10
+ gem 'spork', '~> 1.0rc'
11
+ gem 'yard'
12
+ gem 'simplecov'
13
+ gem 'sqlite3'
14
+
15
+ # Other development dependancies
16
+ gem 'rake'
17
+
18
+ if RUBY_VERSION == '1.8.7'
19
+ gem 'json_pure'
20
+ end
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+ guard 'bundler' do
4
+ watch('Gemfile')
5
+ watch(/^.+\.gemspec/)
6
+ end
7
+
8
+ guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
9
+ watch('Gemfile')
10
+ watch('Gemfile.lock')
11
+ watch('spec/spec_helper.rb') { :rspec }
12
+ watch(%r{features/support/}) { :cucumber }
13
+ end
14
+
15
+ guard 'rspec', :version => 2 do
16
+ watch(%r{^spec/.+_spec\.rb$})
17
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
18
+ watch('spec/spec_helper.rb') { "spec" }
19
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Liquid Concept
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,370 @@
1
+ gcalMapper
2
+ ==========
3
+
4
+ [![Build Status](https://secure.travis-ci.org/liquidconcept/gcalmapper.png?branch=master)](http://travis-ci.org/liquidconcept/gcalmapper)
5
+
6
+ A library to map Google Calendar events with an ORM.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'gcalmapper'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install gcalmapper
22
+
23
+ Usage
24
+ -----
25
+
26
+ ### Authorization to connect to gcal ##
27
+
28
+ To have access to your google calendar go to :
29
+
30
+ [Google API Console][1]
31
+
32
+ and open a new api account :
33
+
34
+ 1. click on "Services" on the rigth top menu
35
+ 2. click on the toggle button next to "Calendar API"
36
+ 3. accept the license
37
+ 4. click on "API Access" on the rigth top menu
38
+ 5. click on the blue button "Create an Oauth2.0 Client ID ..."
39
+ 6. provide a name for the API and click next
40
+ 7. chose the type between "service account" and "installed app"
41
+ 8. click "create client id"
42
+
43
+ once you have your "installed app" access run :
44
+
45
+ $ gcal-mapper --client_id [CLIENT_ID] --client_secret [CLIENT_SECRET]
46
+
47
+ it should open a new page, click accept that the API acess your data.
48
+ this gives you ~/google_auth.yaml copy it on spec/file/google_auth.yaml
49
+ (you can change path with --file /path/to/the/yaml_file.yaml)
50
+ (you can change scope with --scope https://www.googleapis.com/another/scope)
51
+
52
+ with the service account make sure you save well the private key.
53
+ You can use service account only if you manage your
54
+ domain with google. But you have to go to your google apps manager :
55
+
56
+ 1. go to "Advenced tools" -> "Manage api client acess"
57
+ 2. enter your client id(service account) in "client name"
58
+ 3. enter "http(s)://www.google.com/calendar/feeds/" in "scope"
59
+ 4. click "authorize"
60
+
61
+ ### exemple ##
62
+
63
+ when you manage to have the authorization to access your google calendar create your model
64
+
65
+ require 'active_record'
66
+
67
+ class Event < ActiveRecord::Base
68
+
69
+ include GcalMapper::Mapper::ActiveRecord
70
+
71
+ calendar do
72
+ configure :file => 'path/to/your/yaml/file.yaml'
73
+
74
+ calendar 'your_email@gmail.com'
75
+
76
+ google_id 'gid'
77
+
78
+ field 'name', :source => 'summary'
79
+ field 'description', :source => 'description',
80
+ :match => /^category: (.*)$/, :default => 'not categorized'
81
+ field 'status', :source => 'status'
82
+ field 'start_at', :source => 'start.dateTime', :if_empty => 'start.date'
83
+ field 'end_at', :source => 'end.dateTime', :if_empty => 'end.date'
84
+ field 'created_at', :source => 'created'
85
+ field 'updated_at', :source => 'updated'
86
+ end
87
+
88
+ def self.synchronize_me
89
+ self.synchronize_calendar
90
+ end
91
+
92
+ end
93
+
94
+ here is an example with Oauth2.0 authentification for installed app, as you can see it'is not a rails model and it work with AtiveRecord.
95
+
96
+ you can find an exemple with rails there :
97
+
98
+ [GcalMapper Rails exemple][3]
99
+
100
+ ### configure ##
101
+
102
+ `configure` is used to set your crendentials. You can see above an exemple for "installed app" here is one for "service account" :
103
+
104
+ configure :file => '/path/to/the/private-key.p12',
105
+ :client_email => 'service_account_email',
106
+ :user_email => 'user@yourdomain.com',
107
+ :password => 'password of your key'
108
+
109
+ `:password` is optional the default value is 'notasecret'
110
+
111
+
112
+ ### google_id ##
113
+
114
+ `google_id` must be present, and you must give it the name of an existing string field in your DB. it store the google event id and must be saved to keep your DB synchronize
115
+
116
+
117
+ ### calendar ##
118
+
119
+ if you want to synchronize more than one calendar just do someting like :
120
+
121
+ calendar 'your_email@gmail.com'
122
+ calendar 'other_accessible_calendar@gmail.com
123
+
124
+
125
+ ### field ##
126
+
127
+ the minimal `field` declatration is
128
+
129
+ field 'name_of_your_db_column', :source => 'name_of_the_source'
130
+
131
+ It is possible to be more precise with the use of `:match` and `:default`
132
+
133
+ - `:match => 'regexp'` is used to parse
134
+ only a part of the google data
135
+ - `:default => 'default` is used to put default data in case of unmatching data
136
+
137
+ Both are optional, but if you use `:match` without `:default`, the default value will be `nil`
138
+
139
+ if the data you want to save is not always setted, it'is possible to use `:if_empty`.
140
+ this will try to take data in another field if the source is empty. in the exemple you
141
+ can see the usage as date.dateTime is not always present (for exemple long event that only
142
+ date of start and date of end without hours).
143
+
144
+
145
+ Compatibility
146
+ -------------
147
+
148
+ For now GcalMapper is only compatible with :
149
+
150
+ - ActiveRecord
151
+
152
+ it can be extended quite easly
153
+
154
+ it is possible to use GcalMapper without ORM, juste include
155
+
156
+ GcalMapper::Mapper::Simple
157
+
158
+ like this :
159
+
160
+ class Event
161
+ attr_accessor :id, :gid, :name, :description, :status, :start_at, :end_at, :created_at, :upated_at
162
+ include GcalMapper::Mapper::Simple
163
+
164
+ calendar do
165
+
166
+ configure :file => 'path/to/your/yaml/file.yaml'
167
+
168
+ calendar 'your_email@gmail.com'
169
+
170
+ google_id 'gid'
171
+
172
+ field 'name', :source => 'summary'
173
+ field 'description', :source => 'description',
174
+ :match => /^category: (.*)$/, :default => 'not categorized'
175
+ field 'status', :source => 'status'
176
+ field 'start_at', :source => 'start.dateTime'
177
+ field 'end_at', :source => 'end.dateTime'
178
+ field 'created_at', :source => 'created'
179
+ field 'updated_at', :source => 'updated'
180
+ end
181
+
182
+ def self.synchronize_me
183
+ self.synchronize_calendar
184
+ end
185
+
186
+ end
187
+
188
+
189
+ Source data reference
190
+ ---------------------
191
+
192
+ here is the reference for the source data :
193
+
194
+ {
195
+ "kind": "calendar#event",
196
+ "etag": etag,
197
+ "id": string,
198
+ "status": string,
199
+ "htmlLink": string,
200
+ "created": datetime,
201
+ "updated": datetime,
202
+ "summary": string,
203
+ "description": string,
204
+ "location": string,
205
+ "colorId": string,
206
+ "creator": {
207
+ "email": string,
208
+ "displayName": string
209
+ },
210
+ "organizer": {
211
+ "email": string,
212
+ "displayName": string
213
+ },
214
+ "start": {
215
+ "date": date,
216
+ "dateTime": datetime,
217
+ "timeZone": string
218
+ },
219
+ "end": {
220
+ "date": date,
221
+ "dateTime": datetime,
222
+ "timeZone": string
223
+ },
224
+ "recurrence": [
225
+ string
226
+ ],
227
+ "recurringEventId": string,
228
+ "originalStartTime": {
229
+ "date": date,
230
+ "dateTime": datetime,
231
+ "timeZone": string
232
+ },
233
+ "transparency": string,
234
+ "visibility": string,
235
+ "iCalUID": string,
236
+ "sequence": integer,
237
+ "attendees": [
238
+ {
239
+ "email": string,
240
+ "displayName": string,
241
+ "organizer": boolean,
242
+ "self": boolean,
243
+ "resource": boolean,
244
+ "optional": boolean,
245
+ "responseStatus": string,
246
+ "comment": string,
247
+ "additionalGuests": integer
248
+ }
249
+ ],
250
+ "attendeesOmitted": boolean,
251
+ "extendedProperties": {
252
+ "private": {
253
+ (key): string
254
+ },
255
+ "shared": {
256
+ (key): string
257
+ }
258
+ },
259
+ "gadget": {
260
+ "type": string,
261
+ "title": string,
262
+ "link": string,
263
+ "iconLink": string,
264
+ "width": integer,
265
+ "height": integer,
266
+ "display": string,
267
+ "preferences": {
268
+ (key): string
269
+ }
270
+ },
271
+ "anyoneCanAddSelf": boolean,
272
+ "guestsCanInviteOthers": boolean,
273
+ "guestsCanModify": boolean,
274
+ "guestsCanSeeOtherGuests": boolean,
275
+ "privateCopy": boolean,
276
+ "reminders": {
277
+ "useDefault": boolean,
278
+ "overrides": [
279
+ {
280
+ "method": string,
281
+ "minutes": integer
282
+ }
283
+ ]
284
+ }
285
+ }
286
+
287
+ for now you can access nearly all the data. you can acces all the the first and second degree key.
288
+
289
+ if you want the summary :
290
+
291
+ field 'summary', :source => 'summary'
292
+
293
+ for the creator email :
294
+
295
+ field 'creator_email', :source => 'creator.email'
296
+
297
+ if you just put `creator` it will give your the string dump of
298
+
299
+ "organizer": {
300
+ "email": string,
301
+ "displayName": string
302
+ },
303
+
304
+ that will look like :
305
+
306
+ "{\"email\"=>\"string\", \"displayName\"=>\"string\"}"
307
+
308
+ for things like `attendees` or `extendedProperties`, the only way of saving it is to save the string dump of that
309
+
310
+ for `attendees` :
311
+
312
+ field 'attendees_dump', :source 'attendees'
313
+
314
+ for `extendedProperties` you can do `extendedProperties.private` but `extendedProperties.private.(field)` will not work
315
+
316
+
317
+ Test
318
+ ----
319
+
320
+ to launch test you need to have files to do both authentification methodes
321
+
322
+ execute, with the data of the installed app
323
+
324
+ gcal-mapper --client_id [CLIENT_ID] --client_secret [CLIENT_SECRET]
325
+
326
+ copy the file ".p12" to "spec/file/privatekey.p12"
327
+ copy the file "~/google_auth.yaml" to "spec/file/google_auth.yaml"
328
+
329
+
330
+ then create spec/file/config.yaml, must look like this :
331
+
332
+ p12: 'spec/file/privatekey.p12' -> path to your p12 key
333
+ p12_2: 'spec/file/privatekey2.p12' -> path to a second one, can be the same
334
+ client_email: '[your service account's email address]'
335
+ user_email: '[email address that your service account can impersonate]'
336
+ yaml: 'spec/file/google_auth.yaml' -> or another path
337
+ yaml_relative: '~/google_auth.yaml' -> or another path, relative
338
+ bad_yaml: 'spec/file/bad_yaml.yaml' -> create an empty file
339
+ calendar_id: '[an accesible calendar id, possibly the same at user email]'
340
+
341
+ then run
342
+
343
+ rake spec
344
+
345
+ test's are running!
346
+
347
+ ### Warning ##
348
+
349
+ Ruby 1.8.7 does not support the vcr cassettes generate by 1.9.x, but 1.8.7 cassettes work with 1.9.x.
350
+ D'ont forget to remove the cassettes before testing with 1.8.7 if you already tested with 1.9.x.
351
+
352
+ Contributing
353
+ ------------
354
+
355
+ 1. Fork it
356
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
357
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
358
+ 4. Push to the branch (`git push origin my-new-feature`)
359
+ 5. Create new Pull Request
360
+
361
+
362
+ Copyright & License
363
+ -------------------
364
+
365
+ Copyright (c) 2012 Liquid Concept. See LICENSE for details.
366
+
367
+
368
+ [1]: https://code.google.com/apis/console
369
+ [2]: https://developers.google.com/google-apps/calendar/v3/reference/events?hl=fr-FR
370
+ [3]: https://github.com/ndubuis/gcal_mapper-exemple