4me-sdk 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 885049091080590a682f5fa2df6320a55d251ab5
4
+ data.tar.gz: 8f119ed9d892fa6abb55ac2aafafd297a8f2e617
5
+ SHA512:
6
+ metadata.gz: 72ce9082f51ad8f90626f7039a9ce2c67616dd6983616592d92572b9801880b92a033ac18cae8616c254fbdb917e388bfa436a7694324a18b9794a3ce9ac9806
7
+ data.tar.gz: e998fc6b6f19f313039a793cfb7357c9aabf8e05c8a65e67a718c449bed7a5e053a563204dd57f0e946f11d042d08977fde8f2be36f52ca95d2f419f3b3a1103
data/4me-sdk.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sdk4me/client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = '4me-sdk'
8
+ spec.version = Sdk4me::Client::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.required_ruby_version = '>= 2.0.0'
11
+ spec.authors = ['4me']
12
+ spec.email = %q{developers@4me.com}
13
+ spec.description = %q{SDK for accessing the 4me}
14
+ spec.summary = %q{The official 4me SDK for Ruby. Provides easy access to the APIs found at https://developer.4me.com}
15
+ spec.homepage = %q{https://github.com/code4me/4me-sdk-ruby}
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = Dir.glob('lib/**/*') + %w(
19
+ LICENSE
20
+ README.md
21
+ Gemfile
22
+ Gemfile.lock
23
+ 4me-sdk.gemspec
24
+ )
25
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ spec.test_files = `git ls-files -- {test,spec}/*`.split("\n")
27
+ spec.require_paths = ['lib']
28
+ spec.rdoc_options = ['--charset=UTF-8']
29
+
30
+ spec.add_runtime_dependency 'gem_config', '>=0.3'
31
+ spec.add_runtime_dependency 'activesupport', '>= 4.2'
32
+ spec.add_runtime_dependency 'mime-types', '>= 3.0'
33
+
34
+ spec.add_development_dependency 'bundler', '~> 1'
35
+ spec.add_development_dependency 'rake', '~> 12'
36
+ spec.add_development_dependency 'rspec', '~> 3.3'
37
+ spec.add_development_dependency 'webmock', '~> 2'
38
+ spec.add_development_dependency 'simplecov', '~> 0'
39
+
40
+ end
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in 4me-sdk-ruby.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,74 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ 4me-sdk (1.1.2)
5
+ activesupport
6
+ gem_config
7
+ mime-types
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (5.2.1)
13
+ concurrent-ruby (~> 1.0, >= 1.0.2)
14
+ i18n (>= 0.7, < 2)
15
+ minitest (~> 5.1)
16
+ tzinfo (~> 1.1)
17
+ addressable (2.5.2)
18
+ public_suffix (>= 2.0.2, < 4.0)
19
+ concurrent-ruby (1.1.3)
20
+ crack (0.4.3)
21
+ safe_yaml (~> 1.0.0)
22
+ diff-lcs (1.3)
23
+ docile (1.3.1)
24
+ gem_config (0.3.1)
25
+ hashdiff (0.3.7)
26
+ i18n (1.1.1)
27
+ concurrent-ruby (~> 1.0)
28
+ json (2.1.0)
29
+ mime-types (3.2.2)
30
+ mime-types-data (~> 3.2015)
31
+ mime-types-data (3.2018.0812)
32
+ minitest (5.11.3)
33
+ public_suffix (3.0.3)
34
+ rake (12.3.1)
35
+ rspec (3.3.0)
36
+ rspec-core (~> 3.3.0)
37
+ rspec-expectations (~> 3.3.0)
38
+ rspec-mocks (~> 3.3.0)
39
+ rspec-core (3.3.2)
40
+ rspec-support (~> 3.3.0)
41
+ rspec-expectations (3.3.1)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.3.0)
44
+ rspec-mocks (3.3.2)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.3.0)
47
+ rspec-support (3.3.0)
48
+ safe_yaml (1.0.4)
49
+ simplecov (0.16.1)
50
+ docile (~> 1.1)
51
+ json (>= 1.8, < 3)
52
+ simplecov-html (~> 0.10.0)
53
+ simplecov-html (0.10.2)
54
+ thread_safe (0.3.6)
55
+ tzinfo (1.2.5)
56
+ thread_safe (~> 0.1)
57
+ webmock (2.3.2)
58
+ addressable (>= 2.3.6)
59
+ crack (>= 0.3.2)
60
+ hashdiff
61
+
62
+ PLATFORMS
63
+ ruby
64
+
65
+ DEPENDENCIES
66
+ 4me-sdk!
67
+ bundler (~> 1)
68
+ rake (~> 12)
69
+ rspec (~> 3.3)
70
+ simplecov (~> 0)
71
+ webmock (~> 2)
72
+
73
+ BUNDLED WITH
74
+ 1.16.1
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 https://code.4me.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,324 @@
1
+ # Sdk4me::Client
2
+
3
+ Client for accessing the [4me REST API](http://developer.4me.com/v1/)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem '4me-sdk'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install 4me-sdk
18
+
19
+ ## Configuration
20
+
21
+ ### Global
22
+
23
+ ```
24
+ Sdk4me.configure do |config|
25
+ config.api_token = 'd41f5868feb65fc87fa2311a473a8766ea38bc40'
26
+ config.account = 'my-sandbox'
27
+ config.logger = Rails.logger
28
+ ...
29
+ end
30
+ ```
31
+
32
+ All options available:
33
+
34
+ * _logger_: The [Ruby Logger](http://www.ruby-doc.org/stdlib-1.9.3/libdoc/logger/rdoc/Logger.html) instance, default: `Logger.new(STDOUT)`
35
+ * _host_: The [4me API host](http://developer.4me.com/v1/#service-url), default: 'https://api.4me.com'
36
+ * _api_version_: The [4me API version](http://developer.4me.com/v1/#service-url), default: 'v1'
37
+ * _api_token_: (**required**) The [4me API token](http://developer.4me.com/v1/#api-tokens)
38
+ * _account_: Specify a [different account](http://developer.4me.com/v1/#multiple-accounts) to work with
39
+ * _source_: The [source](http://developer.4me.com/v1/general/source/) used when creating new records
40
+ * _max_retry_time_: maximum nr of seconds to wait for server to respond (default = 5400 = 1.5 hours)<br/>
41
+ The sleep time between retries starts at 2 seconds and doubles after each retry, i.e.
42
+ 2, 6, 18, 54, 162, 486, 1458, 4374, 13122, ... seconds.<br/>
43
+ One retry will always be performed unless you set the value to -1.
44
+ * _read_timeout_: [HTTP read timeout](http://ruby-doc.org/stdlib-2.0.0/libdoc/net/http/rdoc/Net/HTTP.html#method-i-read_timeout-3D) in seconds (default = 25)
45
+ * _block_at_rate_limit_: Set to `true` to block the request until the [rate limit](http://developer.4me.com/v1/#rate-limiting) is lifted, default: `false`
46
+ * _proxy_host_: Define in case HTTP traffic needs to go through a proxy
47
+ * _proxy_port_: Port of the proxy, defaults to 8080
48
+ * _proxy_user_: Proxy user
49
+ * _proxy_password_: Proxy password
50
+ * _ca_file_: Certificate file (defaults to the provided ca-bundle.crt file from Mozilla)
51
+
52
+ ### Override
53
+
54
+ Each time an 4me SDK Client is instantiated it is possible to override the [global configuration](#global-configuration) like so:
55
+
56
+ ```
57
+ client = Sdk4me::Client.new(account: 'trusted-sandbox', source: 'my special integration')
58
+ ```
59
+
60
+ ### Proxy
61
+
62
+ The proxy settings are limited to basic authentication only. In case ISA-NTLM authentication is required, make sure to setup a local proxy configured to forward the requests. And example local proxy host for Windows is [Fiddle](http://www.telerik.com/fiddler).
63
+
64
+ ## 4me SDK Client
65
+
66
+ Minimal example:
67
+
68
+ ```
69
+ require 'sdk4me/client'
70
+
71
+ client = Sdk4me::Client.new(api_token: '3a4e4590179263839...')
72
+ response = client.get('me')
73
+ puts response[:primary_email]
74
+ ```
75
+
76
+ ### Retrieve a single record
77
+
78
+ The `get` method can be used to retrieve a single record from SDK4ME.
79
+
80
+ ```
81
+ response = Sdk4me::Client.new.get('organizations/4321')
82
+ puts response[:name]
83
+ ```
84
+
85
+ By default this call will return all [fields](http://developer.4me.com/v1/organizations/#fields) of the Organization.
86
+
87
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
88
+ ```
89
+ response = Sdk4me::Client.new.get('organizations/4321')
90
+ puts response[:parent][:name] # this may throw an error when +parent+ is +nil+
91
+ puts response[:parent, :name] # using this format you will retrieve +nil+ when +parent+ is +nil+
92
+ puts response['parent', 'name'] # strings are also accepted as keys
93
+ ```
94
+
95
+ ### Browse through a collection of records
96
+
97
+ Although the `get` method can be also used to retrieve a collection of records from SDK4ME, the preferred way is to use the `each` method.
98
+
99
+ ```
100
+ count = Sdk4me::Client.new.each('organizations') do |organization|
101
+ puts organization[:name]
102
+ end
103
+ puts "Found #{count} organizations"
104
+ ```
105
+
106
+ By default this call will return all [collection fields](http://developer.4me.com/v1/organizations/#collection-fields) for each Organization.
107
+ For more fields, check out the [field selection](http://developer.4me.com/v1/general/field_selection/#collection-of-resources) documentation.
108
+
109
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
110
+ ```
111
+ count = Sdk4me::Client.new.each('organizations', fields: 'parent') do |organization|
112
+ puts organization[:parent][:name] # this may throw an error when +parent+ is +nil+
113
+ puts organization[:parent, :name] # using this format you will retrieve +nil+ when +parent+ is +nil+
114
+ puts organization['parent', 'name'] # strings are also accepted as keys
115
+ end
116
+ ```
117
+
118
+ Note that an `Sdk4me::Exception` could be thrown in case one of the API requests fails. When using the [blocking options](#blocking) the chances of this happening are rather small and you may decide not to explicitly catch the `Sdk4me::Exception` here, but leave it up to a generic exception handler.
119
+
120
+ ### Retrieve a collection of records
121
+
122
+ The `each` method [described above](#browse-through-a-collection-of-records) is the preferred way to work with collections of data.
123
+
124
+ If you really want to [paginate](http://developer.4me.com/v1/general/pagination/) yourself, the `get` method is your friend.
125
+
126
+ ```
127
+ @client = Sdk4me::Client.new
128
+ response = @client.get('organizations', {per_page: 10, page: 2})
129
+
130
+ puts response.json # all data in an array
131
+
132
+ puts "showing page #{response.current_page}/#{response.total_pages}, with #{response.per_page} records per page"
133
+ puts "total number of records #{response.total_entries}"
134
+
135
+ # retrieve collection for other pages directly from the response
136
+ first_page = @client.get(response.pagination_link(:first))
137
+ prev_page = @client.get(response.pagination_link(:prev))
138
+ next_page = @client.get(response.pagination_link(:next))
139
+ last_page = @client.get(response.pagination_link(:last))
140
+ ```
141
+
142
+ By default this call will return all [collection fields](http://developer.4me.com/v1/organizations/#collection-fields) for each Organization.
143
+ For more fields, check out the [field selection](http://developer.4me.com/v1/general/field_selection/#collection-of-resources) documentation.
144
+
145
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
146
+ ```
147
+ response = Sdk4me::Client.new.get('organizations', {per_page: 10, page: 2, fields: 'parent'})
148
+ puts response[:parent, :name] # an array with the parent organization names
149
+ puts response['parent', 'name'] # strings are also accepted as keys
150
+ ```
151
+
152
+ ### Create a new record
153
+
154
+ Creating new records is done using the `post` method.
155
+
156
+ ```
157
+ response = Sdk4me::Client.new.post('people', {primary_email: 'new.user@example.com', organization_id: 777})
158
+ if response.valid?
159
+ puts "New person created with id #{response[:id]}"
160
+ else
161
+ puts response.message
162
+ end
163
+ ```
164
+
165
+ Make sure to validate the success by calling `response.valid?` and to take appropriate action in case the response is not valid.
166
+
167
+
168
+ ### Update an existing record
169
+
170
+ Updating records is done using the `put` method.
171
+
172
+ ```
173
+ response = Sdk4me::Client.new.put('people/888', {name: 'Mrs. Susan Smith', organization_id: 777})
174
+ if response.valid?
175
+ puts "Person with id #{response[:id]} successfully updated"
176
+ else
177
+ puts response.message
178
+ end
179
+ ```
180
+
181
+ Make sure to validate the success by calling `response.valid?` and to take appropriate action in case the response is not valid.
182
+
183
+ ### Delete an existing record
184
+
185
+ Deleting records is done using the `delete` method.
186
+
187
+ ```
188
+ response = Sdk4me::Client.new.delete('organizations/88/addresses/')
189
+ if response.valid?
190
+ puts "Addresses of Organization with id #{response[:id]} successfully removed"
191
+ else
192
+ puts response.message
193
+ end
194
+ ```
195
+
196
+ Make sure to validate the success by calling `response.valid?` and to take appropriate action in case the response is not valid.
197
+
198
+
199
+ ### Note Attachments
200
+
201
+ To add attachments to a note is rather tricky when done manually as it involves separate file uploads to Amazon S3 and sending
202
+ confirmations back to 4me.
203
+
204
+ To make it easy, a special `attachments` parameter can be added when using the `post` or `put` method when the `note` field is available.
205
+
206
+ ```
207
+ response = Sdk4me::Client.new.put('requests/416621', {
208
+ status: 'waiting_for_customer',
209
+ note: 'Please complete the attached forms and reassign the request back to us.',
210
+ attachments: ['/tmp/forms/Inventory.xls', '/tmp/forms/PersonalData.xls']
211
+ })
212
+ ```
213
+
214
+ If an attachment upload fails, the errors are logged but the `post` or `put` request will still be sent to 4me without the
215
+ failed attachments. To receive exceptions add `attachments_exception: true` to the data.
216
+
217
+ ```
218
+ begin
219
+ response = Sdk4me::Client.new.put('requests/416621', {
220
+ status: 'waiting_for_customer',
221
+ note: 'Please complete the attached forms and reassign the request back to us.',
222
+ attachments: ['/tmp/forms/Inventory.xls', '/tmp/forms/PersonalData.xls']
223
+ })
224
+ if response.valid?
225
+ puts "Request #{response[:id]} updated and attachments added to the note"
226
+ else
227
+ puts "Update of request failed: #{response.message}"
228
+ end
229
+ catch Sdk4me::UploadFailed => ex
230
+ puts "Could not upload an attachment: #{ex.message}"
231
+ end
232
+ ```
233
+
234
+ ### Importing CSV files
235
+
236
+ 4me also provides an [Import API](http://developer.4me.com/v1/import/). The 4me SDK Client can be used to upload files to that API.
237
+
238
+ ```
239
+ response = Sdk4me::Client.new.import('\tmp\people.csv', 'people')
240
+ if response.valid?
241
+ puts "Import queued with token #{response[:token]}"
242
+ else
243
+ puts "Import upload failed: #{response.message}"
244
+ end
245
+
246
+ ```
247
+
248
+ The second argument contains the [import type](http://developer.4me.com/v1/import/#parameters).
249
+
250
+ It is also possible to [monitor the progress](http://developer.4me.com/v1/import/#import-progress) of the import and block until the import is complete. In that case you will need to add some exception handling to your code.
251
+
252
+ ```
253
+ begin
254
+ response = Sdk4me::Client.new.import('\tmp\people.csv', 'people', true)
255
+ puts response[:state]
256
+ puts response[:results]
257
+ puts response[:message]
258
+ catch Sdk4me::UploadFailed => ex
259
+ puts "Could not upload the people import file: #{ex.message}"
260
+ catch Sdk4me::Exception => ex
261
+ puts "Unable to monitor progress of the people import: #{ex.message}"
262
+ end
263
+ ```
264
+
265
+ Note that blocking for the import to finish is required when you import multiple CSVs that are dependent on each other.
266
+
267
+
268
+ ### Exporting CSV files
269
+
270
+ 4me also provides an [Export API](http://developer.4me.com/v1/export/). The 4me SDK Client can be used to download (zipped) CSV files using that API.
271
+
272
+ ```
273
+ response = Sdk4me::Client.new.export(['people', 'people_contact_details'], DateTime.new(2012,03,30,23,00,00))
274
+ if response.valid?
275
+ puts "Export queued with token #{response[:token]}"
276
+ else
277
+ puts "Export failed: #{response.message}"
278
+ end
279
+
280
+ ```
281
+
282
+ The first argument contains the [export types](http://developer.4me.com/v1/export/#parameters).
283
+ The second argument is optional and limits the export to all changed records since the given time.
284
+
285
+ It is also possible to [monitor the progress](http://developer.4me.com/v1/export/#export-progress) of the export and block until the export is complete. In that case you will need to add some exception handling to your code.
286
+
287
+ ```
288
+ require 'open-uri'
289
+
290
+ begin
291
+ response = Sdk4me::Client.new.export(['people', 'people_contact_details'], nil, true)
292
+ puts response[:state]
293
+ # write the export file to disk
294
+ File.open('/tmp/export.zip', 'wb') { |f| f.write(open(response[:url]).read) }
295
+ catch Sdk4me::UploadFailed => ex
296
+ puts "Could not queue the people export: #{ex.message}"
297
+ catch Sdk4me::Exception => ex
298
+ puts "Unable to monitor progress of the people export: #{ex.message}"
299
+ end
300
+ ```
301
+
302
+ Note that blocking for the export to finish is recommended as you will get direct access to the exported file.
303
+
304
+
305
+ ### Blocking
306
+
307
+ By default all actions on the 4me SDK Client will block until the 4me API is accessible, see the _max_retry_time_ option in the [configuration](#global-configuration). This is especially helpfull for flaky internet connections.
308
+
309
+ By setting the _block_at_rate_limit_ to `true` in the [configuration](#global-configuration) all actions will also block in case the [rate limit](http://developer.4me.com/v1/#rate-limiting) is reached. The action is retried every 5 minutes until the [rate limit](http://developer.4me.com/v1/#rate-limiting) is lifted again, which might take up to 1 hour.
310
+
311
+
312
+ ### Exception handling
313
+
314
+ The standard methods `get`, `post`, `put` and `delete` will always return a Response with an [error message](http://developer.4me.com/v1/#http-status-codes) in case something went wrong.
315
+
316
+ By calling `response.valid?` you will know if the action succeeded or not, and `response.message` provides additinal information in case the response was invalid.
317
+
318
+ ```
319
+ response = Sdk4me::Client.new.get('organizations/1a2b')
320
+ puts response.valid?
321
+ puts response.message
322
+ ```
323
+
324
+ The methods `each` and `import` may throw an `Sdk4me::Exception` in case something failed, see the examples above.