gcal_mapper 0.1.1

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.
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
@@ -0,0 +1,159 @@
1
+ module GcalMapper
2
+ #
3
+ # Provide methods to synch google calendar and local bd
4
+ #
5
+ class Sync
6
+
7
+ # proxy to call sync methods and set new instance
8
+ #
9
+ # @param [Configuration] config configuration class seted by DSL
10
+ # @param [Class] base class of the caller
11
+ def self.sync(config, base)
12
+ new(config, base).sync_gcal
13
+ end
14
+
15
+ # new Sync object
16
+ #
17
+ # @param [Configuration] config configuration class seted by DSL
18
+ # @param [Class] base class of the calle
19
+ def initialize(config, base)
20
+ @config = config
21
+ @base = base
22
+ end
23
+
24
+ # full synchronization step by step
25
+ #
26
+ def sync_gcal
27
+ authenticate
28
+ fetch_events
29
+ save_events
30
+ end
31
+
32
+ private
33
+ # call Authentification class to authenticate the API
34
+ #
35
+ def authenticate
36
+ @auth = GcalMapper::Authentification.new(@config.file, @config.client_email, @config.user_email, @config.password)
37
+ @auth.authenticate
38
+ end
39
+
40
+ # Get all events from specified calendar(s).
41
+ #
42
+ # @return [Array] all events from given calendar(s) id.
43
+ def fetch_events
44
+ events_list = []
45
+
46
+ calendar = GcalMapper::Calendar.new
47
+ retried = false
48
+ begin
49
+ calendars_list = calendar.get_calendars_list(@auth.access_token)
50
+ rescue
51
+ if !retried
52
+ @auth.refresh_token
53
+ retried = true
54
+ retry
55
+ else
56
+ raise
57
+ end
58
+ end
59
+
60
+ if calendars_list.empty?
61
+ raise GcalMapper::CalendarAvailabilityError
62
+ end
63
+
64
+ @config.calendars.each do |cal|
65
+ events_list = []
66
+ if calendars_list.include?(cal)
67
+ retried = false
68
+ begin
69
+ events_list += (calendar.get_events_list(@auth.access_token, cal))
70
+ rescue
71
+ if !retried
72
+ @auth.refresh_token
73
+ retried = true
74
+ retry
75
+ else
76
+ raise
77
+ end
78
+ end
79
+ else
80
+ raise GcalMapper::CalendarAccessibilityError
81
+ end
82
+ end
83
+
84
+ @events_list = events_list
85
+ end
86
+
87
+ # Get all events from specified calendar(s). an keep synchronize with the online gcal
88
+ #
89
+ def save_events
90
+ adapter = Mapper.adapter
91
+
92
+ @events_list.each do |event|
93
+
94
+ existed_event = adapter.find_by(@config.gid, event['id'])
95
+ event_exist = !existed_event.nil?
96
+
97
+ if event_exist
98
+ if event['status'] == 'cancelled'
99
+ adapter.delete!(existed_event.id)
100
+ else
101
+ updated_attrib = set_attrib(event)
102
+ current_attrib = existed_event.attributes
103
+ current_attrib.delete('id')
104
+ if current_attrib != updated_attrib
105
+ adapter.update!(existed_event.id, updated_attrib)
106
+ end
107
+ end
108
+ end
109
+
110
+ if !event_exist && event['status'] != 'cancelled'
111
+ adapter.create!(set_attrib(event))
112
+ end
113
+ end
114
+ end
115
+
116
+ # set the object from fields configuration
117
+ #
118
+ # @param [Hash] event event to save in obj
119
+ # @return [hash] hash of setted attributes
120
+ def set_attrib(event)
121
+ attrib_hash = {@config.gid => event['id']}
122
+ @config.fields.each do |field, source|
123
+ if source[:source].include?('.')
124
+ data = source[:source].split('.')
125
+ attrib_hash[field] = eval_value(source, event[data[0]][data[1]])
126
+ else
127
+ attrib_hash[field] = eval_value(source, event[source[:source]])
128
+ end
129
+ if (attrib_hash[field].nil? && source.has_key?(:if_empty))
130
+ if source[:if_empty].include?('.')
131
+ data = source[:if_empty].split('.')
132
+ attrib_hash[field] = eval_value(source, event[data[0]][data[1]])
133
+ else
134
+ attrib_hash[field] = eval_value(source, event[source[:if_empty]])
135
+ end
136
+ end
137
+ end
138
+
139
+ attrib_hash
140
+ end
141
+
142
+ # eval the value from the source options
143
+ #
144
+ # @param [Hash] source source of the field
145
+ # @param [string] raw_data the string extract form google event data
146
+ # @return the data asked
147
+ def eval_value(source, raw_data)
148
+ if source[:match]
149
+ data = source[:match].match(raw_data).to_s
150
+ data = source[:default] if data == ''
151
+ else
152
+ data = raw_data
153
+ end
154
+
155
+ data
156
+ end
157
+
158
+ end
159
+ end
@@ -0,0 +1,4 @@
1
+ module GcalMapper
2
+ #version number of GcalMapper
3
+ VERSION = '0.1.1'
4
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Authentification::Assertion do
4
+
5
+ it "should have access_token attribute", :vcr do
6
+ auth = GcalMapper::Authentification::Assertion.new(@p12, @client_email, @user_email, 'notasecret')
7
+ auth.should respond_to(:access_token)
8
+ end
9
+
10
+ it "should have refresh_token attribute", :vcr do
11
+ auth = GcalMapper::Authentification::Assertion.new(@p12, @client_email, @user_email, 'notasecret')
12
+ auth.should respond_to(:refresh_token)
13
+ end
14
+
15
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Authentification::Base do
4
+ before :all do
5
+ class DummyClass < GcalMapper::Authentification::Base
6
+ end
7
+
8
+ @dummy = DummyClass.new
9
+ end
10
+
11
+ it "should raise error if access_token don't exist" do
12
+ expect {@dummy.access_token}.to raise_error(NotImplementedError)
13
+ end
14
+
15
+ it "should raise error if refresh_token don't exist" do
16
+ expect {@dummy.refresh_token}.to raise_error(NotImplementedError)
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Authentification::Oauth2 do
4
+
5
+ it "should have access_token attribute" do
6
+ auth = GcalMapper::Authentification::Oauth2.new(@yaml)
7
+ auth.should respond_to(:access_token)
8
+ end
9
+
10
+ it "should have refresh_token attribute", :vcr do
11
+ auth = GcalMapper::Authentification::Oauth2.new(@yaml)
12
+ auth.should respond_to(:refresh_token)
13
+ end
14
+
15
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Authentification do
4
+
5
+ it "should raise an error if the file is don't exist" do
6
+ expect {GcalMapper::Authentification.new('/home/test')}.to raise_error
7
+ end
8
+
9
+ it "should return an error if bad yaml file is given" do
10
+ auth = GcalMapper::Authentification.new(@bad_yaml)
11
+ expect {auth.authenticate}.to raise_error
12
+ end
13
+
14
+ it "should not raise an error if relative path is given" do
15
+ auth = GcalMapper::Authentification.new(@yaml_relative)
16
+ expect {auth.authenticate}.to_not raise_error
17
+ end
18
+
19
+ it "access token should exist with oauth2 auth" do
20
+ auth = GcalMapper::Authentification.new(@yaml)
21
+ auth.authenticate.should be_true
22
+ end
23
+
24
+ it "access token should exist with assertion auth", :vcr do
25
+ auth = GcalMapper::Authentification.new(@p12, @client_email)
26
+ auth.authenticate.should be_true
27
+ end
28
+
29
+ it "should be fasle if bad client email is given", :vcr do
30
+ auth = GcalMapper::Authentification.new(@p12, 'test@dtest.com')
31
+ expect {auth.authenticate}.to raise_error
32
+ end
33
+
34
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Calendar do
4
+ before :all do
5
+ @auth_oauth2 = GcalMapper::Authentification.new(@yaml)
6
+ @auth_oauth2.authenticate
7
+ @list = GcalMapper::Calendar.new
8
+ @bad_token = 'a bad token'
9
+
10
+ end
11
+
12
+ it "should get the calendar list", :vcr do
13
+ begin
14
+ calendar = @list.get_calendars_list(@auth_oauth2.access_token)
15
+ rescue
16
+ @auth_oauth2.refresh_token
17
+ calendar = @list.get_calendars_list(@auth_oauth2.access_token)
18
+ end
19
+ @list.get_calendars_list(@auth_oauth2.access_token).should_not be_nil
20
+ end
21
+
22
+ it "should get the events list", :vcr do
23
+ @list.get_events_list(@auth_oauth2.access_token, @calendar_id).should_not be_nil
24
+ end
25
+
26
+ it "should raise error if the token is bad", :vcr do
27
+ expect {@list.get_calendars_list(@bad_token)}.to raise_error
28
+ end
29
+
30
+ it "should raise error if the calendar id isn't accessible", :vcr do
31
+ expect {@list.get_events_list(@auth_oauth2.access_token, 'test')}.to raise_error
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper do
4
+
5
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Mapper::ActiveRecord do
4
+
5
+ before :all do
6
+ class User < ActiveRecord::Base
7
+
8
+ end
9
+
10
+ @klass = GcalMapper::Mapper::ActiveRecord::ActiveRecord.new(User)
11
+ end
12
+
13
+ it "should create a new object and save it" do
14
+ @klass.create!({'first_name' => 'a_name', 'name' => 'a_name'})
15
+ User.all.should_not eql([])
16
+ end
17
+
18
+ it "shoudl list all stored entry" do
19
+ @klass.find_all.should eql(User.all)
20
+ end
21
+
22
+ it "should update an entry" do
23
+ user = User.first
24
+ name_before = user.name
25
+ @klass.update!(user.id, {'name' => 'another_name'})
26
+ name_after = User.first.name
27
+
28
+ name_before.should_not eql(name_after)
29
+ end
30
+
31
+ it "should delete an entry" do
32
+ user = User.first
33
+ @klass.delete!(user.id)
34
+
35
+ User.all.should eql([])
36
+ end
37
+
38
+ it "should find an entry from field name and value" do
39
+ @klass.create!({'first_name' => 'a_name', 'name' => 'a_name'})
40
+ @klass.create!({'first_name' => 'a_name', 'name' => 'another_name'})
41
+ @klass.create!({'first_name' => 'a_name', 'name' => 'different_name'})
42
+
43
+ @klass.find_by('name', 'a_name').should be_an_instance_of(User)
44
+ end
45
+
46
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Mapper::DSL do
4
+ before :all do
5
+ @dsl = GcalMapper::Mapper::DSL.new(GcalMapper::Configuration.new)
6
+ end
7
+
8
+ describe :field do
9
+ it "should raise error if field option don't exist" do
10
+ expect {@dsl.field('test', {:source => 'test', :test => 'test'})}.to raise_error
11
+ end
12
+
13
+ it "should accept :source, :match, :default" do
14
+ expect {@dsl.field('test', {:source => 'test', :match => /test/, :default => 'test'})}.to_not raise_error
15
+ end
16
+
17
+ it "should raise error if regexp is invalid" do
18
+ expect {@dsl.field('test', {:source => 'test', :match => test, :default => 'test'})}.to raise_error
19
+ end
20
+
21
+ it "should raise error if :source isn't present" do
22
+ expect {@dsl.field('test', {:match => /test/, :default => 'test'})}.to raise_error
23
+ end
24
+ end
25
+
26
+ describe :configure do
27
+ it "should raise an error if :file isn't present" do
28
+ expect {@dsl.configure({:client_email => '87', :user_email => 'web', :password => 'notasecret'})}.to raise_error
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Mapper::Simple do
4
+ before :all do
5
+ class User2
6
+ include GcalMapper::Mapper::Simple
7
+ attr_accessor :id, :first_name, :name
8
+
9
+ end
10
+
11
+ @base = GcalMapper::Mapper::Simple::Simple.new(User2)
12
+ end
13
+
14
+ it "should create a new object and save it" do
15
+ @base.create!({'first_name' => 'a_name', 'name' => 'a_name'})
16
+ @base.events.should_not eql([])
17
+ end
18
+
19
+ it "shoudl list all stored entry" do
20
+ @base.find_all.should eql(@base.events)
21
+ end
22
+
23
+ it "should update an entry" do
24
+ user = @base.events[0]
25
+ name_before = user.name
26
+ @base.update!(user.id, {'name' => 'another_name'})
27
+ name_after = @base.events[0].name
28
+
29
+ name_before.should_not eql(name_after)
30
+ end
31
+
32
+ it "should delete an entry" do
33
+ @base.create!({'first_name' => 'a_name', 'name' => 'a_name'})
34
+ before_count = @base.events.count
35
+ user = @base.events[0]
36
+ @base.delete!(user.id)
37
+
38
+ before_count.should > (@base.events.count)
39
+ end
40
+
41
+ it "should find an entry from field name and value" do
42
+ @base.create!({'first_name' => 'a_name', 'name' => 'another_name'})
43
+ @base.create!({'first_name' => 'a_name', 'name' => 'different_name'})
44
+
45
+ @base.find_by('name', 'a_name').should be_an_instance_of(User2)
46
+ end
47
+
48
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe GcalMapper::Mapper do
4
+
5
+ before :all do
6
+ load File.dirname(__FILE__) + '/support/models/event.rb'
7
+ end
8
+
9
+ it "should load a file containing DSL with no error" do
10
+ expect{load File.dirname(__FILE__) + '/support/models/event.rb'}.to_not raise_error
11
+ end
12
+
13
+ it "should save all events", :vcr do
14
+ Event.synchronize_calendar
15
+ Event.all.should_not eql([])
16
+ end
17
+
18
+ it "should save events only once", :vcr do
19
+ before = Event.count
20
+ Event.synchronize_calendar
21
+ Event.count.should eq(before)
22
+ end
23
+
24
+ it "should erase cancelled event", :vcr do
25
+ cancelled = 0
26
+ Event.all.each do |event|
27
+ cancelled += 1 if event.status == 'cancelled'
28
+ end
29
+ cancelled.should eq(0)
30
+ end
31
+
32
+ end