contextio 0.5.0 → 1.0.0

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 (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