itrp-client 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzMxOGY1Yzg5YmViZTBkODhlN2Q2MjM2ZmZiZDg0ZmMyZGJlM2QyYw==
5
+ data.tar.gz: !binary |-
6
+ NmRmY2MwMmQ2OGUwYTE0MmViYzJlZTE2NzE4ZDlhYTIxNjQ4OWU1NA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NGZlYjg2NzZkYzllNDU4NWM4MDdlNjU2NGU0NjczZjZkOGZlOTFkMDQ5ODk2
10
+ ZTg4YjdjNzY5ZWJhYmQ1YTY5MWRlZWU1MzcyZjExNzA4ZDQ3YWY1OWY3ODI0
11
+ MmE4YjdmNTg5OGJjYTVkNTc1ZjJlOTBlN2FiZDUxY2ZiNmJjNGE=
12
+ data.tar.gz: !binary |-
13
+ YWRmZTQyMzNhMWViNmZkODQyMTM4YmM1MDNjZWVhNmVjMTEyY2E5NDVkYjlk
14
+ NDA1MzExM2Y4ZmZkNmI4NTNiMWFjNThiOGQwYWQzOGFmNTA4MTU3ZjIwYmY0
15
+ MTAwZDZjNjAxYThhZGI3NWQ5YjA0NTYxYzc4YWU4NDUwNTJhMTY=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in itrp-client.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ itrp-client (1.0.0)
5
+ activesupport
6
+ gem_config
7
+ mime-types
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activesupport (4.0.1)
13
+ i18n (~> 0.6, >= 0.6.4)
14
+ minitest (~> 4.2)
15
+ multi_json (~> 1.3)
16
+ thread_safe (~> 0.1)
17
+ tzinfo (~> 0.3.37)
18
+ addressable (2.3.5)
19
+ atomic (1.1.14)
20
+ crack (0.4.1)
21
+ safe_yaml (~> 0.9.0)
22
+ diff-lcs (1.2.4)
23
+ gem_config (0.2.4)
24
+ i18n (0.6.5)
25
+ mime-types (2.0)
26
+ minitest (4.7.5)
27
+ multi_json (1.8.0)
28
+ rake (10.1.0)
29
+ rspec (2.14.1)
30
+ rspec-core (~> 2.14.0)
31
+ rspec-expectations (~> 2.14.0)
32
+ rspec-mocks (~> 2.14.0)
33
+ rspec-core (2.14.5)
34
+ rspec-expectations (2.14.2)
35
+ diff-lcs (>= 1.1.3, < 2.0)
36
+ rspec-mocks (2.14.3)
37
+ safe_yaml (0.9.5)
38
+ simplecov (0.7.1)
39
+ multi_json (~> 1.0)
40
+ simplecov-html (~> 0.7.1)
41
+ simplecov-html (0.7.1)
42
+ thread_safe (0.1.3)
43
+ atomic
44
+ tzinfo (0.3.38)
45
+ webmock (1.13.0)
46
+ addressable (>= 2.2.7)
47
+ crack (>= 0.3.2)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ bundler (~> 1.3)
54
+ itrp-client!
55
+ rake
56
+ rspec
57
+ simplecov
58
+ webmock
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 ITRP Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,304 @@
1
+ # Itrp::Client
2
+
3
+ Client for accessing the [ITRP REST API](http://developer.itrp.com/v1/)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'itrp-client'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install itrp-client
18
+
19
+ ## Configuration
20
+
21
+ ### Global
22
+
23
+ ```
24
+ Itrp.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 [ITRP API host](http://developer.itrp.com/v1/#service-url), default: 'https://api.itrp.com'
36
+ * _api_version_: The [ITRP API version](http://developer.itrp.com/v1/#service-url), default: 'v1'
37
+ * _api_token_: (**required**) The [ITRP API token](http://developer.itrp.com/v1/#api-tokens)
38
+ * _account_: Specify a [different account](http://developer.itrp.com/v1/#multiple-accounts) to work with
39
+ * _source_: The [source](http://developer.itrp.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.itrp.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
+
51
+ ### Override
52
+
53
+ Each time an ITRP Client is instantiated it is possible to override the [global configuration](#global-configuration) like so:
54
+
55
+ ```
56
+ client = Itrp::Client.new(account: 'trusted-sandbox', source: 'my special integration')
57
+ ```
58
+
59
+ ## ITRP Client
60
+
61
+ Minimal example:
62
+
63
+ ```
64
+ require 'itrp/client'
65
+
66
+ client = Itrp::Client.new(api_token: '3a4e4590179263839...')
67
+ response = client.get('me')
68
+ puts response[:primary_email]
69
+ ```
70
+
71
+ ### Retrieve a single record
72
+
73
+ The `get` method can be used to retrieve a single record from ITRP.
74
+
75
+ ```
76
+ response = Itrp::Client.new.get('organizations/4321')
77
+ puts response[:name]
78
+ ```
79
+
80
+ By default this call will return all [fields](http://developer.itrp.com/v1/organizations/#fields) of the Organization.
81
+
82
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
83
+ ```
84
+ response = Itrp::Client.new.get('organizations/4321')
85
+ puts response[:parent][:name] # this may throw an error when +parent+ is +nil+
86
+ puts response[:parent, :name] # using this format you will retrieve +nil+ when +parent+ is +nil+
87
+ puts response['parent', 'name'] # strings are also accepted as keys
88
+ ```
89
+
90
+ ### Browse through a collection of records
91
+
92
+ Although the `get` method can be also used to retrieve a collection of records from ITRP, the preferred way is to use the `each` method.
93
+
94
+ ```
95
+ count = Itrp::Client.new.each('organizations') do |organization|
96
+ puts organization[:name]
97
+ end
98
+ puts "Found #{count} organizations"
99
+ ```
100
+
101
+ By default this call will return all [collection fields](http://developer.itrp.com/v1/organizations/#collection-fields) for each Organization.
102
+ For more fields, check out the [field selection](http://developer.itrp.com/v1/general/field_selection/#collection-of-resources) documentation.
103
+
104
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
105
+ ```
106
+ count = Itrp::Client.new.each('organizations', fields: 'parent') do |organization|
107
+ puts organization[:parent][:name] # this may throw an error when +parent+ is +nil+
108
+ puts organization[:parent, :name] # using this format you will retrieve +nil+ when +parent+ is +nil+
109
+ puts organization['parent', 'name'] # strings are also accepted as keys
110
+ end
111
+ ```
112
+
113
+ Note that an `Itrp::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 `Itrp::Exception` here, but leave it up to a generic exception handler.
114
+
115
+ ### Retrieve a collection of records
116
+
117
+ The `each` method [described above](#browse-through-a-collection-of-records) is the preferred way to work with collections of data.
118
+
119
+ If you really want to [paginate](http://developer.itrp.com/v1/general/pagination/) yourself, the `get` method is your friend.
120
+
121
+ ```
122
+ @client = Itrp::Client.new
123
+ response = @client.get('organizations', {per_page: 10, page: 2})
124
+
125
+ puts response.json # all data in an array
126
+
127
+ puts "showing page #{response.current_page}/#{response.total_pages}, with #{response.per_page} records per page"
128
+ puts "total number of records #{response.total_entries}"
129
+
130
+ # retrieve collection for other pages directly from the response
131
+ first_page = @client.get(response.pagination_link(:first))
132
+ prev_page = @client.get(response.pagination_link(:prev))
133
+ next_page = @client.get(response.pagination_link(:next))
134
+ last_page = @client.get(response.pagination_link(:last))
135
+ ```
136
+
137
+ By default this call will return all [collection fields](http://developer.itrp.com/v1/organizations/#collection-fields) for each Organization.
138
+ For more fields, check out the [field selection](http://developer.itrp.com/v1/general/field_selection/#collection-of-resources) documentation.
139
+
140
+ The fields can be accessed using *symbols* and *strings*, and it is possible chain a number of keys in one go:
141
+ ```
142
+ response = Itrp::Client.new.get('organizations', {per_page: 10, page: 2, fields: 'parent'})
143
+ puts response[:parent, :name] # an array with the parent organization names
144
+ puts response['parent', 'name'] # strings are also accepted as keys
145
+ ```
146
+
147
+ ### Create a new record
148
+
149
+ Creating new records is done using the `post` method.
150
+
151
+ ```
152
+ response = Itrp::Client.new.post('people', {primary_email: 'new.user@example.com', organization_id: 777})
153
+ if response.valid?
154
+ puts "New person created with id #{response[:id]}"
155
+ else
156
+ puts response.message
157
+ end
158
+ ```
159
+
160
+ Make sure to validate the success by calling `response.valid?` and to take appropriate action in case the response is not valid.
161
+
162
+
163
+ ### Update an existing record
164
+
165
+ Updating records is done using the `put` method.
166
+
167
+ ```
168
+ response = Itrp::Client.new.put('people/888', {name: 'Mrs. Susan Smith', organization_id: 777})
169
+ if response.valid?
170
+ puts "Person with id #{response[:id]} successfully updated"
171
+ else
172
+ puts response.message
173
+ end
174
+ ```
175
+
176
+ Make sure to validate the success by calling `response.valid?` and to take appropriate action in case the response is not valid.
177
+
178
+
179
+ ### Note Attachments
180
+
181
+ To add attachments to a note is rather tricky when done manually as it involves separate file uploads to Amazon S3 and sending
182
+ confirmations back to ITRP.
183
+
184
+ To make it easy, a special `attachments` parameter can be added when using the `post` or `put` method when the `note` field is available.
185
+
186
+ ```
187
+ response = Itrp::Client.new.put('requests/416621', {
188
+ status: 'waiting_for_customer',
189
+ note: 'Please complete the attached forms and reassign the request back to us.',
190
+ attachments: ['/tmp/forms/Inventory.xls', '/tmp/forms/PersonalData.xls']
191
+ })
192
+ ```
193
+
194
+ If an attachment upload fails, the errors are logged but the `post` or `put` request will still be sent to ITRP without the
195
+ failed attachments. To receive exceptions add `attachments_exception: true` to the data.
196
+
197
+ ```
198
+ begin
199
+ response = Itrp::Client.new.put('requests/416621', {
200
+ status: 'waiting_for_customer',
201
+ note: 'Please complete the attached forms and reassign the request back to us.',
202
+ attachments: ['/tmp/forms/Inventory.xls', '/tmp/forms/PersonalData.xls']
203
+ })
204
+ if response.valid?
205
+ puts "Request #{response[:id]} updated and attachments added to the note"
206
+ else
207
+ puts "Update of request failed: #{response.message}"
208
+ end
209
+ catch Itrp::UploadFailed => ex
210
+ puts "Could not upload an attachment: #{ex.message}"
211
+ end
212
+ ```
213
+
214
+ ### Importing CSV files
215
+
216
+ ITRP also provides an [Import API](http://developer.itrp.com/v1/import/). The ITRP Client can be used to upload files to that API.
217
+
218
+ ```
219
+ response = Itrp::Client.new.import('\tmp\people.csv', 'people')
220
+ if response.valid?
221
+ puts "Import queued with token #{response[:token]}"
222
+ else
223
+ puts "Import upload failed: #{response.message}"
224
+ end
225
+
226
+ ```
227
+
228
+ The second argument contains the [import type](http://developer.itrp.com/v1/import/#parameters).
229
+
230
+ It is also possible to [monitor the progress](http://developer.itrp.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.
231
+
232
+ ```
233
+ begin
234
+ response = Itrp::Client.new.import('\tmp\people.csv', 'people', true)
235
+ puts response[:state]
236
+ puts response[:results]
237
+ puts response[:message]
238
+ catch Itrp::UploadFailed => ex
239
+ puts "Could not upload the people import file: #{ex.message}"
240
+ catch Itrp::Exception => ex
241
+ puts "Unable to monitor progress of the people import: #{ex.message}"
242
+ end
243
+ ```
244
+
245
+ Note that blocking for the import to finish is required when you import multiple CSVs that are dependent on each other.
246
+
247
+
248
+ ### Exporting CSV files
249
+
250
+ ITRP also provides an [Export API](http://developer.itrp.com/v1/export/). The ITRP Client can be used to download (zipped) CSV files using that API.
251
+
252
+ ```
253
+ response = Itrp::Client.new.export(['people', 'people_contact_details'], DateTime.new(2012,03,30,23,00,00))
254
+ if response.valid?
255
+ puts "Export queued with token #{response[:token]}"
256
+ else
257
+ puts "Export failed: #{response.message}"
258
+ end
259
+
260
+ ```
261
+
262
+ The first argument contains the [export types](http://developer.itrp.com/v1/export/#parameters).
263
+ The second argument is optional and limits the export to all changed records since the given time.
264
+
265
+ It is also possible to [monitor the progress](http://developer.itrp.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.
266
+
267
+ ```
268
+ require 'open-uri'
269
+
270
+ begin
271
+ response = Itrp::Client.new.export(['people', 'people_contact_details'], nil, true)
272
+ puts response[:state]
273
+ # write the export file to disk
274
+ File.open('/tmp/export.zip', 'wb') { |f| f.write(open(response[:url]).read) }
275
+ catch Itrp::UploadFailed => ex
276
+ puts "Could not queue the people export: #{ex.message}"
277
+ catch Itrp::Exception => ex
278
+ puts "Unable to monitor progress of the people export: #{ex.message}"
279
+ end
280
+ ```
281
+
282
+ Note that blocking for the export to finish is recommended as you will get direct access to the exported file.
283
+
284
+
285
+ ### Blocking
286
+
287
+ By default all actions on the ITRP Client will block until the ITRP API is accessible, see the _max_retry_time_ option in the [configuration](#global-configuration). This is especially helpfull for flaky internet connections.
288
+
289
+ 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.itrp.com/v1/#rate-limiting) is reached. The action is retried every 5 minutes until the [rate limit](http://developer.itrp.com/v1/#rate-limiting) is lifted again, which might take up to 1 hour.
290
+
291
+
292
+ ### Exception handling
293
+
294
+ The standard methods `get`, `post`, `put` and `delete` will always return a Response with an [error message](http://developer.itrp.com/v1/#http-status-codes) in case something went wrong.
295
+
296
+ 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.
297
+
298
+ ```
299
+ response = Itrp::Client.new.get('organizations/1a2b')
300
+ puts response.valid?
301
+ puts response.message
302
+ ```
303
+
304
+ The methods `each` and `import` may throw an `Itrp::Exception` in case something failed, see the examples above.
@@ -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 'itrp/client/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "itrp-client"
8
+ spec.version = Itrp::Client::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.required_ruby_version = '>= 1.9.3'
11
+ spec.authors = ["ITRP"]
12
+ spec.email = %q{developers@itrp.com}
13
+ spec.description = %q{Client for accessing the ITRP REST API}
14
+ spec.summary = %q{Client for accessing the ITRP REST API}
15
+ spec.homepage = "https://developer.itrp.com"
16
+ spec.license = "MIT"
17
+
18
+ spec.files = Dir.glob("lib/**/*") + [
19
+ "LICENSE.txt",
20
+ "README.md",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "itrp-client.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'
31
+ spec.add_runtime_dependency 'activesupport'
32
+ spec.add_runtime_dependency 'mime-types'
33
+
34
+ spec.add_development_dependency "bundler", "~> 1.3"
35
+ spec.add_development_dependency "rake"
36
+ spec.add_development_dependency 'rspec'
37
+ spec.add_development_dependency 'webmock'
38
+ spec.add_development_dependency 'simplecov'
39
+
40
+ end