contextio 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.document +4 -0
  2. data/.gitignore +8 -0
  3. data/.rspec +1 -0
  4. data/.yardopts +1 -0
  5. data/ChangeLog.md +5 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +62 -22
  9. data/Rakefile +46 -36
  10. data/contextio.gemspec +30 -0
  11. data/lib/contextio.rb +69 -583
  12. data/lib/contextio/account.rb +132 -0
  13. data/lib/contextio/account_collection.rb +57 -0
  14. data/lib/contextio/account_sync_data.rb +22 -0
  15. data/lib/contextio/api.rb +162 -0
  16. data/lib/contextio/api/association_helpers.rb +17 -0
  17. data/lib/contextio/api/resource.rb +230 -0
  18. data/lib/contextio/api/resource_collection.rb +174 -0
  19. data/lib/contextio/api/url_builder.rb +153 -0
  20. data/lib/contextio/body_part.rb +45 -0
  21. data/lib/contextio/body_part_collection.rb +13 -0
  22. data/lib/contextio/connect_token.rb +57 -0
  23. data/lib/contextio/connect_token_collection.rb +44 -0
  24. data/lib/contextio/contact.rb +43 -0
  25. data/lib/contextio/contact_collection.rb +21 -0
  26. data/lib/contextio/email_address.rb +53 -0
  27. data/lib/contextio/email_address_collection.rb +21 -0
  28. data/lib/contextio/email_settings.rb +146 -0
  29. data/lib/contextio/file.rb +92 -0
  30. data/lib/contextio/file_collection.rb +13 -0
  31. data/lib/contextio/folder.rb +56 -0
  32. data/lib/contextio/folder_collection.rb +18 -0
  33. data/lib/contextio/folder_sync_data.rb +32 -0
  34. data/lib/contextio/message.rb +96 -0
  35. data/lib/contextio/message_collection.rb +35 -0
  36. data/lib/contextio/oauth_provider.rb +29 -0
  37. data/lib/contextio/oauth_provider_collection.rb +46 -0
  38. data/lib/contextio/source.rb +55 -0
  39. data/lib/contextio/source_collection.rb +41 -0
  40. data/lib/contextio/source_sync_data.rb +23 -0
  41. data/lib/contextio/thread.rb +15 -0
  42. data/lib/contextio/thread_collection.rb +25 -0
  43. data/lib/contextio/version.rb +11 -0
  44. data/lib/contextio/webhook.rb +39 -0
  45. data/lib/contextio/webhook_collection.rb +26 -0
  46. data/spec/config.yml.example +3 -0
  47. data/spec/contextio/account_collection_spec.rb +78 -0
  48. data/spec/contextio/account_spec.rb +52 -0
  49. data/spec/contextio/api/association_helpers_spec.rb +28 -0
  50. data/spec/contextio/api/resource_collection_spec.rb +286 -0
  51. data/spec/contextio/api/resource_spec.rb +467 -0
  52. data/spec/contextio/api/url_builder_spec.rb +78 -0
  53. data/spec/contextio/api_spec.rb +123 -0
  54. data/spec/contextio/connect_token_collection_spec.rb +74 -0
  55. data/spec/contextio/connect_token_spec.rb +58 -0
  56. data/spec/contextio/email_settings_spec.rb +112 -0
  57. data/spec/contextio/oauth_provider_collection_spec.rb +36 -0
  58. data/spec/contextio/oauth_provider_spec.rb +120 -0
  59. data/spec/contextio/source_collection_spec.rb +57 -0
  60. data/spec/contextio/source_spec.rb +52 -0
  61. data/spec/contextio/version_spec.rb +10 -0
  62. data/spec/contextio_spec.rb +64 -0
  63. data/spec/spec_helper.rb +17 -0
  64. metadata +234 -12
  65. data/README.textile +0 -29
@@ -0,0 +1,26 @@
1
+ require_relative 'api/resource_collection'
2
+ require_relative 'webhook'
3
+
4
+ class ContextIO
5
+ class WebhookCollection
6
+ include ContextIO::API::ResourceCollection
7
+
8
+ self.resource_class = ContextIO::Webhook
9
+ self.association_name = :webhooks
10
+
11
+ belongs_to :account
12
+
13
+ def create(success_callback_url, failure_callback_url, options={})
14
+ api_args = options.merge(
15
+ 'callback_url' => success_callback_url,
16
+ 'failure_notif_url' => failure_callback_url
17
+ )
18
+
19
+ result_hash = api.request(:post, resource_url, api_args)
20
+
21
+ result_hash.delete('success')
22
+
23
+ resource_class.new(api, result_hash)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ key: 12345
3
+ secret: 54321
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+ require 'contextio/account_collection'
3
+
4
+ describe ContextIO::AccountCollection do
5
+ let(:api) { double('API', url_for: 'url from api') }
6
+
7
+ subject { ContextIO::AccountCollection.new(api) }
8
+
9
+ describe "#create" do
10
+ before do
11
+ api.stub(:request).with(:post, anything, anything).and_return(
12
+ 'success' => true,
13
+ 'id' => '1234',
14
+ 'resource_url' => 'resource_url'
15
+ )
16
+ end
17
+
18
+ context "without where constraints" do
19
+ it "requires an email address" do
20
+ expect { subject.create(first_name: 'Bruno') }.to raise_error(ArgumentError)
21
+ end
22
+
23
+ it "posts to the api" do
24
+ api.should_receive(:request).with(
25
+ :post,
26
+ 'url from api',
27
+ hash_including(email: 'hello@email.com')
28
+ )
29
+
30
+ subject.create(email: 'hello@email.com')
31
+ end
32
+
33
+ it "doesn't make any more API calls than it needs to" do
34
+ api.should_not_receive(:request).with(:get, anything, anything)
35
+
36
+ subject.create(email: 'hello@email.com')
37
+ end
38
+
39
+ it "returns an Account" do
40
+ expect(subject.create(email: 'hello@email.com')).to be_a(ContextIO::Account)
41
+ end
42
+
43
+ it "takes an optional first name" do
44
+ api.should_receive(:request).with(
45
+ anything,
46
+ anything,
47
+ hash_including(first_name: 'Bruno')
48
+ )
49
+
50
+ subject.create(email: 'hello@email.com', first_name: 'Bruno')
51
+ end
52
+
53
+ it "takes an optional last name" do
54
+ api.should_receive(:request).with(
55
+ anything,
56
+ anything,
57
+ hash_including(last_name: 'Morency')
58
+ )
59
+
60
+ subject.create(email: 'hello@email.com', last_name: 'Morency')
61
+ end
62
+ end
63
+
64
+ context "with email in the where constraints" do
65
+ subject { ContextIO::AccountCollection.new(api).where(email: 'hello@email.com')}
66
+
67
+ it "allows a missing email address" do
68
+ expect { subject.create(first_name: 'Bruno') }.to_not raise_error(ArgumentError)
69
+ end
70
+
71
+ it "uses the email address from the where constraints" do
72
+ api.should_receive(:request).with(anything, anything, hash_including(email: 'hello@email.com'))
73
+
74
+ subject.create(first_name: 'Bruno')
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'contextio/account'
3
+
4
+ describe ContextIO::Account do
5
+ let(:api) { double('api', url_for: 'url from api') }
6
+
7
+ subject { ContextIO::Account.new(api, id: '1234') }
8
+
9
+ describe ".new" do
10
+ context "with an id passed in" do
11
+ it "doesn't raise an error" do
12
+ expect { ContextIO::Account.new(api, id: '1234') }.to_not raise_error
13
+ end
14
+ end
15
+
16
+ context "with neither an id nor a resource_url passed in" do
17
+ it "raises an ArgumentError" do
18
+ expect { ContextIO::Account.new(api, foo: 'bar') }.to raise_error(ArgumentError)
19
+ end
20
+ end
21
+ end
22
+
23
+ describe "#update" do
24
+ before do
25
+ api.stub(:request).and_return({'success' => true})
26
+ end
27
+
28
+ subject { ContextIO::Account.new(api, id: '1234', first_name: 'old first name') }
29
+
30
+ it "posts to the api" do
31
+ api.should_receive(:request).with(
32
+ :post,
33
+ 'url from api',
34
+ first_name: 'new first name'
35
+ )
36
+
37
+ subject.update(first_name: 'new first name')
38
+ end
39
+
40
+ it "updates the object" do
41
+ subject.update(first_name: 'new first name')
42
+
43
+ expect(subject.first_name).to eq('new first name')
44
+ end
45
+
46
+ it "doesn't make any more API calls than it needs to" do
47
+ api.should_not_receive(:request).with(:get, anything, anything)
48
+
49
+ subject.update(first_name: 'new first name')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'contextio/api/association_helpers'
3
+
4
+ describe "ContextIO::API::AssociationHelpers" do
5
+ subject { ContextIO::API::AssociationHelpers }
6
+
7
+ describe ".class_for_association_name" do
8
+ context "when the resource is registered" do
9
+ let(:resource_class) do
10
+ Class.new
11
+ end
12
+
13
+ before do
14
+ subject.register_resource(resource_class, :registered)
15
+ end
16
+
17
+ it "makes the resource available" do
18
+ expect(subject.class_for_association_name(:registered)).to be(resource_class)
19
+ end
20
+ end
21
+
22
+ context "when the resource is NOT registered" do
23
+ it "returns nil" do
24
+ expect(subject.class_for_association_name(:not_registered)).to be_nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,286 @@
1
+ require 'spec_helper'
2
+ require 'contextio/api/resource_collection'
3
+
4
+ class SingularHelper
5
+ def initialize(*args); end
6
+ def self.primary_key; 'token'; end
7
+ end
8
+
9
+ class Owner
10
+ def self.primary_key; 'id'; end
11
+ def id; 4; end
12
+ def initialize(*args); end
13
+
14
+ ContextIO::API::AssociationHelpers.register_resource(self, :owner)
15
+ end
16
+
17
+ describe ContextIO::API::ResourceCollection do
18
+ let(:api) { double('api', url_for: 'url from api') }
19
+
20
+ describe ".resource_class=" do
21
+ let(:helper_class) do
22
+ Class.new do
23
+ include ContextIO::API::ResourceCollection
24
+
25
+ self.resource_class = SingularHelper
26
+ end
27
+ end
28
+
29
+ subject do
30
+ helper_class.new(api)
31
+ end
32
+
33
+ it "makes the class available to instances of the collection" do
34
+ expect(subject.resource_class).to eq(SingularHelper)
35
+ end
36
+ end
37
+
38
+ describe ".belongs_to" do
39
+ let(:helper_class) do
40
+ Class.new do
41
+ include ContextIO::API::ResourceCollection
42
+
43
+ belongs_to :owner
44
+
45
+ self.association_name = :helper_class
46
+ self.resource_class = SingularHelper
47
+ end
48
+ end
49
+
50
+ let(:owner) { Owner.new }
51
+
52
+ subject { helper_class.new(api, owner: owner) }
53
+
54
+ it "makes the belonged-to object available" do
55
+ expect(subject.owner).to eq(owner)
56
+ end
57
+ end
58
+
59
+ describe "#api" do
60
+ let(:helper_class) do
61
+ Class.new do
62
+ include ContextIO::API::ResourceCollection
63
+ end
64
+ end
65
+
66
+ subject do
67
+ helper_class.new(api)
68
+ end
69
+
70
+ it "holds a reference to the api" do
71
+ expect(subject.api).to eq(api)
72
+ end
73
+ end
74
+
75
+ describe ".where" do
76
+ let(:helper_class) do
77
+ Class.new do
78
+ include ContextIO::API::ResourceCollection
79
+
80
+ belongs_to :owner
81
+
82
+ self.resource_class = SingularHelper
83
+ end
84
+ end
85
+
86
+ subject do
87
+ helper_class.new(api, owner: :relation)
88
+ end
89
+
90
+ it "limits the scope of subsequent #each calls" do
91
+ api.should_receive(:request).with(anything, anything, foo: 'bar').and_return([])
92
+
93
+ subject.where(foo: 'bar').each { }
94
+ end
95
+
96
+ it "returns a new object, not the same one, modified" do
97
+ expect(subject.where(foo: 'bar')).to_not be(subject)
98
+ end
99
+
100
+ it "returns a collection object" do
101
+ expect(subject.where(foo: 'bar')).to be_a(helper_class)
102
+ end
103
+
104
+ it "makes the constraints available" do
105
+ expect(subject.where(foo: 'bar').where_constraints).to eq(foo: 'bar')
106
+ end
107
+
108
+ it "overrides older constraints with newer ones" do
109
+ expect(subject.where(foo: 'bar').where(foo: 'baz').where_constraints).to eq(foo: 'baz')
110
+ end
111
+
112
+ it "keeps collection relations from the old to new object" do
113
+ expect(subject.where(foo: 'bar').owner).to eq(subject.owner)
114
+ end
115
+ end
116
+
117
+ describe "#each" do
118
+ let(:helper_class) do
119
+ Class.new do
120
+ include ContextIO::API::ResourceCollection
121
+
122
+ self.resource_class = SingularHelper
123
+ end
124
+ end
125
+
126
+ context "when no attribute hashes are passed in at creation" do
127
+ subject do
128
+ helper_class.new(api)
129
+ end
130
+
131
+ before do
132
+ api.stub(:request).and_return([{key: 'value 1'}, {key: 'value 2'}])
133
+ end
134
+
135
+ it "yields instances of the singular resource class" do
136
+ subject.each do |x|
137
+ expect(x).to be_a(SingularHelper)
138
+ end
139
+ end
140
+
141
+ it "gets attributes for the resources from the api" do
142
+ api.should_receive(:request).exactly(:once).with(:get, 'url from api', {})
143
+
144
+ subject.each { }
145
+ end
146
+
147
+ it "passes the api to the singular resource instances" do
148
+ SingularHelper.should_receive(:new).exactly(:twice).with(api, anything)
149
+
150
+ subject.each { }
151
+ end
152
+
153
+ it "passes attributes to the singular resource instances" do
154
+ SingularHelper.should_receive(:new).exactly(:once).with(anything, key: 'value 1')
155
+ SingularHelper.should_receive(:new).exactly(:once).with(anything, key: 'value 2')
156
+
157
+ subject.each { }
158
+ end
159
+
160
+ context "with a belonged-to resource" do
161
+ let(:helper_class) do
162
+ Class.new do
163
+ include ContextIO::API::ResourceCollection
164
+
165
+ belongs_to :owner
166
+
167
+ self.resource_class = SingularHelper
168
+ end
169
+ end
170
+
171
+ let(:owner) { Owner.new }
172
+
173
+ subject do
174
+ helper_class.new(api, owner: owner)
175
+ end
176
+
177
+ it "passes the belonged-to resource to the singular resource instances" do
178
+ SingularHelper.should_receive(:new).exactly(:twice).with(
179
+ anything,
180
+ hash_including(owner: owner)
181
+ )
182
+
183
+ subject.each { }
184
+ end
185
+ end
186
+ end
187
+
188
+ context "when attribute hashes are passed in at creation" do
189
+ subject do
190
+ helper_class.new(api, attribute_hashes: [{foo: 'bar'}, {foo: 'baz'}])
191
+ end
192
+
193
+ it "yields instances of the singular resource class" do
194
+ subject.each do |x|
195
+ expect(x).to be_a(SingularHelper)
196
+ end
197
+ end
198
+
199
+ it "doesn't hit the API" do
200
+ api.should_not_receive(:request)
201
+
202
+ subject.each { }
203
+ end
204
+
205
+ it "passes the api to the singular resource instances" do
206
+ SingularHelper.should_receive(:new).exactly(:twice).with(api, anything)
207
+
208
+ subject.each { }
209
+ end
210
+
211
+ it "passes attributes to the singular resource instances" do
212
+ SingularHelper.should_receive(:new).exactly(:once).with(anything, foo: 'bar')
213
+ SingularHelper.should_receive(:new).exactly(:once).with(anything, foo: 'baz')
214
+
215
+ subject.each { }
216
+ end
217
+
218
+ context "with a belonged-to resource" do
219
+ let(:helper_class) do
220
+ Class.new do
221
+ include ContextIO::API::ResourceCollection
222
+
223
+ belongs_to :owner
224
+
225
+ self.resource_class = SingularHelper
226
+ end
227
+ end
228
+
229
+ let(:owner) { Owner.new }
230
+
231
+ subject do
232
+ helper_class.new(
233
+ api,
234
+ attribute_hashes: [{foo: 'bar'}, {foo: 'baz'}],
235
+ owner: owner
236
+ )
237
+ end
238
+
239
+ it "passes the belonged-to resource to the singular resource instances" do
240
+ SingularHelper.should_receive(:new).exactly(:twice).with(
241
+ anything,
242
+ hash_including(owner: owner)
243
+ )
244
+
245
+ subject.each { }
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ describe "#[]" do
252
+ let(:helper_class) do
253
+ Class.new do
254
+ include ContextIO::API::ResourceCollection
255
+
256
+ self.resource_class = SingularHelper
257
+ end
258
+ end
259
+
260
+ subject do
261
+ helper_class.new(api)
262
+ end
263
+
264
+ it "returns a new instance of the resource class" do
265
+ expect(subject[1234]).to be_a(SingularHelper)
266
+ end
267
+
268
+ it "feeds the given key to the resource class" do
269
+ SingularHelper.should_receive(:new).with(anything, 'token' => 1234)
270
+
271
+ subject[1234]
272
+ end
273
+
274
+ it "feeds the api to the resource class" do
275
+ SingularHelper.should_receive(:new).with(api, anything)
276
+
277
+ subject[1234]
278
+ end
279
+
280
+ it "doesn't hit the API" do
281
+ api.should_not_receive(:request)
282
+
283
+ subject[1234]
284
+ end
285
+ end
286
+ end