zendesk_api 1.37.0 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zendesk_api/client.rb +29 -25
- data/lib/zendesk_api/collection.rb +53 -78
- data/lib/zendesk_api/configuration.rb +3 -0
- data/lib/zendesk_api/error.rb +1 -6
- data/lib/zendesk_api/helpers.rb +4 -0
- data/lib/zendesk_api/middleware/request/encode_json.rb +0 -1
- data/lib/zendesk_api/middleware/response/callback.rb +1 -1
- data/lib/zendesk_api/middleware/response/deflate.rb +5 -4
- data/lib/zendesk_api/middleware/response/gzip.rb +5 -4
- data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +1 -1
- data/lib/zendesk_api/middleware/response/parse_json.rb +1 -2
- data/lib/zendesk_api/middleware/response/sanitize_response.rb +1 -1
- data/lib/zendesk_api/pagination.rb +99 -0
- data/lib/zendesk_api/resource.rb +19 -10
- data/lib/zendesk_api/resources.rb +118 -22
- data/lib/zendesk_api/search.rb +4 -0
- data/lib/zendesk_api/verbs.rb +6 -8
- data/lib/zendesk_api/version.rb +1 -1
- data/lib/zendesk_api.rb +4 -0
- metadata +26 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ecc2ccbe7be3ec6da2b36fdcd7b75004fcecd91a26de63d0bb561dcddff86cc
|
4
|
+
data.tar.gz: c4b7a7d6baa3246d2835251d03d2a7c0fd69961fd2ca3575a7486f3a7adf06f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9183c973ac61c198dd69d975c5bc9eb27cc424b47e50027d32c2a462f651b08681925b00fd4686d248b615a80445c34b59273861a164917ea6738b54d04c1a4b
|
7
|
+
data.tar.gz: 980637e5be8ba003774a6fe5fe53dc2a4003ba6e58b933d21aaba66cb9c66eb0dd3f706ac6b2e69740f1c22cfe2a3d4c7301a7cfd313c0753ef3cff7cbc2683b
|
data/lib/zendesk_api/client.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
|
3
1
|
require 'zendesk_api/version'
|
4
2
|
require 'zendesk_api/sideloading'
|
5
3
|
require 'zendesk_api/configuration'
|
@@ -26,7 +24,7 @@ module ZendeskAPI
|
|
26
24
|
# The top-level class that handles configuration and connection to the Zendesk API.
|
27
25
|
# Can also be used as an accessor to resource collections.
|
28
26
|
class Client
|
29
|
-
GZIP_EXCEPTIONS = [:em_http, :httpclient]
|
27
|
+
GZIP_EXCEPTIONS = [:em_http, :httpclient, :httpx]
|
30
28
|
|
31
29
|
# @return [Configuration] Config instance
|
32
30
|
attr_reader :config
|
@@ -39,24 +37,25 @@ module ZendeskAPI
|
|
39
37
|
def method_missing(method, *args, &block)
|
40
38
|
method = method.to_s
|
41
39
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
42
|
-
|
43
40
|
unless config.use_resource_cache
|
44
|
-
|
45
|
-
|
41
|
+
resource_class = resource_class_for(method)
|
42
|
+
raise "Resource for #{method} does not exist" unless resource_class
|
43
|
+
return ZendeskAPI::Collection.new(self, resource_class, options)
|
46
44
|
end
|
47
45
|
|
48
46
|
@resource_cache[method] ||= { :class => nil, :cache => ZendeskAPI::LRUCache.new }
|
49
47
|
if !options.delete(:reload) && (cached = @resource_cache[method][:cache].read(options.hash))
|
50
48
|
cached
|
51
49
|
else
|
52
|
-
@resource_cache[method][:class] ||=
|
50
|
+
@resource_cache[method][:class] ||= resource_class_for(method)
|
53
51
|
raise "Resource for #{method} does not exist" unless @resource_cache[method][:class]
|
54
52
|
@resource_cache[method][:cache].write(options.hash, ZendeskAPI::Collection.new(self, @resource_cache[method][:class], options))
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
58
56
|
def respond_to?(method, *args)
|
59
|
-
|
57
|
+
cache = @resource_cache[method]
|
58
|
+
!!(cache.to_h[:class] || resource_class_for(method) || super)
|
60
59
|
end
|
61
60
|
|
62
61
|
# Returns the current user (aka me)
|
@@ -100,9 +99,7 @@ module ZendeskAPI
|
|
100
99
|
config.retry = !!config.retry # nil -> false
|
101
100
|
|
102
101
|
set_raise_error_when_rated_limited
|
103
|
-
|
104
102
|
set_token_auth
|
105
|
-
|
106
103
|
set_default_logger
|
107
104
|
add_warning_callback
|
108
105
|
end
|
@@ -112,7 +109,6 @@ module ZendeskAPI
|
|
112
109
|
# @return [Faraday::Connection] Faraday connection for the client
|
113
110
|
def connection
|
114
111
|
@connection ||= build_connection
|
115
|
-
return @connection
|
116
112
|
end
|
117
113
|
|
118
114
|
# Pushes a callback onto the stack. Callbacks are executed on responses, last in the Faraday middleware stack.
|
@@ -155,7 +151,6 @@ module ZendeskAPI
|
|
155
151
|
builder.use ZendeskAPI::Middleware::Response::ParseIsoDates
|
156
152
|
builder.use ZendeskAPI::Middleware::Response::ParseJson
|
157
153
|
builder.use ZendeskAPI::Middleware::Response::SanitizeResponse
|
158
|
-
|
159
154
|
adapter = config.adapter || Faraday.default_adapter
|
160
155
|
|
161
156
|
unless GZIP_EXCEPTIONS.include?(adapter)
|
@@ -163,14 +158,7 @@ module ZendeskAPI
|
|
163
158
|
builder.use ZendeskAPI::Middleware::Response::Deflate
|
164
159
|
end
|
165
160
|
|
166
|
-
|
167
|
-
if config.access_token && !config.url_based_access_token
|
168
|
-
builder.request(:authorization, "Bearer", config.access_token)
|
169
|
-
elsif config.access_token
|
170
|
-
builder.use ZendeskAPI::Middleware::Request::UrlBasedAccessToken, config.access_token
|
171
|
-
else
|
172
|
-
builder.use Faraday::Request::BasicAuthentication, config.username, config.password
|
173
|
-
end
|
161
|
+
set_authentication(builder, config)
|
174
162
|
|
175
163
|
if config.cache
|
176
164
|
builder.use ZendeskAPI::Middleware::Request::EtagCache, :cache => config.cache
|
@@ -181,20 +169,25 @@ module ZendeskAPI
|
|
181
169
|
builder.use ZendeskAPI::Middleware::Request::EncodeJson
|
182
170
|
|
183
171
|
# Should always be first in the stack
|
184
|
-
|
172
|
+
if config.retry
|
173
|
+
builder.use ZendeskAPI::Middleware::Request::Retry,
|
174
|
+
:logger => config.logger,
|
175
|
+
:retry_codes => config.retry_codes,
|
176
|
+
:retry_on_exception => config.retry_on_exception
|
177
|
+
end
|
185
178
|
if config.raise_error_when_rate_limited
|
186
179
|
builder.use ZendeskAPI::Middleware::Request::RaiseRateLimited, :logger => config.logger
|
187
180
|
end
|
188
181
|
|
189
|
-
builder.adapter(*adapter)
|
182
|
+
builder.adapter(*adapter, &config.adapter_proc)
|
190
183
|
end
|
191
184
|
end
|
192
185
|
|
193
186
|
private
|
194
187
|
|
195
|
-
def
|
196
|
-
|
197
|
-
ZendeskAPI::Association.class_from_namespace(
|
188
|
+
def resource_class_for(method)
|
189
|
+
resource_name = ZendeskAPI::Helpers.modulize_string(Inflection.singular(method.to_s.gsub(/\W/, '')))
|
190
|
+
ZendeskAPI::Association.class_from_namespace(resource_name)
|
198
191
|
end
|
199
192
|
|
200
193
|
def check_url
|
@@ -239,5 +232,16 @@ module ZendeskAPI
|
|
239
232
|
end
|
240
233
|
end
|
241
234
|
end
|
235
|
+
|
236
|
+
# See https://lostisland.github.io/faraday/middleware/authentication
|
237
|
+
def set_authentication(builder, config)
|
238
|
+
if config.access_token && !config.url_based_access_token
|
239
|
+
builder.request :authorization, "Bearer", config.access_token
|
240
|
+
elsif config.access_token
|
241
|
+
builder.use ZendeskAPI::Middleware::Request::UrlBasedAccessToken, config.access_token
|
242
|
+
else
|
243
|
+
builder.request :authorization, :basic, config.username, config.password
|
244
|
+
end
|
245
|
+
end
|
242
246
|
end
|
243
247
|
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'zendesk_api/resource'
|
2
2
|
require 'zendesk_api/resources'
|
3
3
|
require 'zendesk_api/search'
|
4
|
+
require 'zendesk_api/pagination'
|
4
5
|
|
5
6
|
module ZendeskAPI
|
6
7
|
# Represents a collection of resources. Lazily loaded, resources aren't
|
7
8
|
# actually fetched until explicitly needed (e.g. #each, {#fetch}).
|
8
9
|
class Collection
|
9
10
|
include ZendeskAPI::Sideloading
|
11
|
+
include Pagination
|
10
12
|
|
11
13
|
# Options passed in that are automatically converted from an array to a comma-separated list.
|
12
14
|
SPECIALLY_JOINED_PARAMS = [:ids, :only]
|
@@ -114,30 +116,6 @@ module ZendeskAPI
|
|
114
116
|
@count || -1
|
115
117
|
end
|
116
118
|
|
117
|
-
# Changes the per_page option. Returns self, so it can be chained. No execution.
|
118
|
-
# @return [Collection] self
|
119
|
-
def per_page(count)
|
120
|
-
clear_cache if count
|
121
|
-
@options["per_page"] = count
|
122
|
-
self
|
123
|
-
end
|
124
|
-
|
125
|
-
# Changes the page option. Returns self, so it can be chained. No execution.
|
126
|
-
# @return [Collection] self
|
127
|
-
def page(number)
|
128
|
-
clear_cache if number
|
129
|
-
@options["page"] = number
|
130
|
-
self
|
131
|
-
end
|
132
|
-
|
133
|
-
def first_page?
|
134
|
-
!@prev_page
|
135
|
-
end
|
136
|
-
|
137
|
-
def last_page?
|
138
|
-
!@next_page || @next_page == @query
|
139
|
-
end
|
140
|
-
|
141
119
|
# Saves all newly created resources stored in this collection.
|
142
120
|
# @return [Collection] self
|
143
121
|
def save
|
@@ -186,17 +164,8 @@ module ZendeskAPI
|
|
186
164
|
elsif association && association.options.parent && association.options.parent.new_record?
|
187
165
|
return (@resources = [])
|
188
166
|
end
|
189
|
-
path_query_link = (@query || path)
|
190
|
-
|
191
|
-
@response = get_response(path_query_link)
|
192
|
-
|
193
|
-
if path_query_link == "search/export"
|
194
|
-
handle_cursor_response(@response.body)
|
195
|
-
else
|
196
|
-
handle_response(@response.body)
|
197
|
-
end
|
198
167
|
|
199
|
-
@
|
168
|
+
get_resources(@query || path)
|
200
169
|
end
|
201
170
|
|
202
171
|
def fetch(*args)
|
@@ -252,10 +221,12 @@ module ZendeskAPI
|
|
252
221
|
# * If there is a next_page url cached, it executes a fetch on that url and returns the results.
|
253
222
|
# * Otherwise, returns an empty array.
|
254
223
|
def next
|
255
|
-
if @options["page"]
|
224
|
+
if @options["page"] && !cbp_request?
|
256
225
|
clear_cache
|
257
|
-
@options["page"]
|
226
|
+
@options["page"] = @options["page"].to_i + 1
|
258
227
|
elsif (@query = @next_page)
|
228
|
+
# Send _only_ url param "?page[after]=token" to get the next page
|
229
|
+
@options.page&.delete("before")
|
259
230
|
fetch(true)
|
260
231
|
else
|
261
232
|
clear_cache
|
@@ -268,10 +239,12 @@ module ZendeskAPI
|
|
268
239
|
# * If there is a prev_page url cached, it executes a fetch on that url and returns the results.
|
269
240
|
# * Otherwise, returns an empty array.
|
270
241
|
def prev
|
271
|
-
if
|
242
|
+
if !cbp_request? && @options["page"].to_i > 1
|
272
243
|
clear_cache
|
273
244
|
@options["page"] -= 1
|
274
245
|
elsif (@query = @prev_page)
|
246
|
+
# Send _only_ url param "?page[before]=token" to get the prev page
|
247
|
+
@options.page&.delete("after")
|
275
248
|
fetch(true)
|
276
249
|
else
|
277
250
|
clear_cache
|
@@ -326,22 +299,13 @@ module ZendeskAPI
|
|
326
299
|
map(&:to_param)
|
327
300
|
end
|
328
301
|
|
329
|
-
def more_results?(response)
|
330
|
-
response["meta"].present? && response["results"].present?
|
331
|
-
end
|
332
|
-
alias_method :has_more_results?, :more_results? # For backward compatibility with 1.33.0 and 1.34.0
|
333
|
-
|
334
|
-
def get_response_body(link)
|
335
|
-
@client.connection.send("get", link).body
|
336
|
-
end
|
337
|
-
|
338
302
|
def get_next_page_data(original_response_body)
|
339
303
|
link = original_response_body["links"]["next"]
|
340
|
-
|
304
|
+
result_key = @resource_class.model_key || "results"
|
341
305
|
while link
|
342
|
-
response =
|
306
|
+
response = @client.connection.send("get", link).body
|
343
307
|
|
344
|
-
original_response_body[
|
308
|
+
original_response_body[result_key] = original_response_body[result_key] + response[result_key]
|
345
309
|
|
346
310
|
link = response["meta"]["has_more"] ? response["links"]["next"] : nil
|
347
311
|
end
|
@@ -351,14 +315,20 @@ module ZendeskAPI
|
|
351
315
|
|
352
316
|
private
|
353
317
|
|
354
|
-
def
|
355
|
-
|
356
|
-
|
318
|
+
def get_resources(path_query_link)
|
319
|
+
if intentional_obp_request?
|
320
|
+
warn "Offset Based Pagination will be deprecated soon"
|
321
|
+
elsif supports_cbp? && first_cbp_request?
|
322
|
+
# only set cbp options if it's the first request, otherwise the options would be already in place
|
323
|
+
set_cbp_options
|
324
|
+
end
|
325
|
+
@response = get_response(path_query_link)
|
357
326
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
327
|
+
# Keep pre-existing behaviour for search/export
|
328
|
+
if path_query_link == "search/export"
|
329
|
+
handle_search_export_response(@response.body)
|
330
|
+
else
|
331
|
+
handle_response(@response.body)
|
362
332
|
end
|
363
333
|
end
|
364
334
|
|
@@ -370,13 +340,7 @@ module ZendeskAPI
|
|
370
340
|
|
371
341
|
while (bang ? fetch! : fetch)
|
372
342
|
each do |resource|
|
373
|
-
|
374
|
-
|
375
|
-
if block.arity >= 0
|
376
|
-
arguments = arguments.take(block.arity)
|
377
|
-
end
|
378
|
-
|
379
|
-
block.call(*arguments)
|
343
|
+
block.call(resource, @options["page"] || 1)
|
380
344
|
end
|
381
345
|
|
382
346
|
last_page? ? break : self.next
|
@@ -422,7 +386,7 @@ module ZendeskAPI
|
|
422
386
|
|
423
387
|
def get_response(path)
|
424
388
|
@error = nil
|
425
|
-
@
|
389
|
+
@client.connection.send(@verb || "get", path) do |req|
|
426
390
|
opts = @options.delete_if { |_, v| v.nil? }
|
427
391
|
|
428
392
|
req.params.merge!(:include => @includes.join(",")) if @includes.any?
|
@@ -435,36 +399,30 @@ module ZendeskAPI
|
|
435
399
|
end
|
436
400
|
end
|
437
401
|
|
438
|
-
def
|
439
|
-
|
440
|
-
raise ZendeskAPI::Error::NetworkError, @response.env
|
441
|
-
end
|
402
|
+
def handle_search_export_response(response_body)
|
403
|
+
assert_valid_response_body(response_body)
|
442
404
|
|
405
|
+
# Note this doesn't happen in #handle_response
|
443
406
|
response_body = get_next_page_data(response_body) if more_results?(response_body)
|
444
407
|
|
445
408
|
body = response_body.dup
|
446
409
|
results = body.delete(@resource_class.model_key) || body.delete("results")
|
447
410
|
|
448
|
-
|
449
|
-
raise ZendeskAPI::Error::ClientError, "Expected #{@resource_class.model_key} or 'results' in response keys: #{body.keys.inspect}"
|
450
|
-
end
|
411
|
+
assert_results(results, body)
|
451
412
|
|
452
413
|
@resources = results.map do |res|
|
453
414
|
wrap_resource(res)
|
454
415
|
end
|
455
416
|
end
|
456
417
|
|
418
|
+
# For both CBP and OBP
|
457
419
|
def handle_response(response_body)
|
458
|
-
|
459
|
-
raise ZendeskAPI::Error::NetworkError, @response.env
|
460
|
-
end
|
420
|
+
assert_valid_response_body(response_body)
|
461
421
|
|
462
422
|
body = response_body.dup
|
463
423
|
results = body.delete(@resource_class.model_key) || body.delete("results")
|
464
424
|
|
465
|
-
|
466
|
-
raise ZendeskAPI::Error::ClientError, "Expected #{@resource_class.model_key} or 'results' in response keys: #{body.keys.inspect}"
|
467
|
-
end
|
425
|
+
assert_results(results, body)
|
468
426
|
|
469
427
|
@resources = results.map do |res|
|
470
428
|
wrap_resource(res)
|
@@ -472,6 +430,8 @@ module ZendeskAPI
|
|
472
430
|
|
473
431
|
set_page_and_count(body)
|
474
432
|
set_includes(@resources, @includes, body)
|
433
|
+
|
434
|
+
@resources
|
475
435
|
end
|
476
436
|
|
477
437
|
# Simplified Associations#wrap_resource
|
@@ -501,9 +461,13 @@ module ZendeskAPI
|
|
501
461
|
to_a.public_send(name, *args, &block)
|
502
462
|
end
|
503
463
|
|
464
|
+
# If you call client.tickets.foo - and foo is not an attribute nor an association, it ends up here, as a new collection
|
504
465
|
def next_collection(name, *args, &block)
|
505
466
|
opts = args.last.is_a?(Hash) ? args.last : {}
|
506
|
-
opts.merge!(:collection_path
|
467
|
+
opts.merge!(collection_path: [*@collection_path, name], page: nil)
|
468
|
+
# Why `page: nil`?
|
469
|
+
# when you do client.tickets.fetch followed by client.tickets.foos => the request to /tickets/foos will
|
470
|
+
# have the options page set to whatever the last options were for the tickets collection
|
507
471
|
self.class.new(@client, @resource_class, @options.merge(opts))
|
508
472
|
end
|
509
473
|
|
@@ -514,5 +478,16 @@ module ZendeskAPI
|
|
514
478
|
def resource_methods
|
515
479
|
@resource_methods ||= @resource_class.singleton_methods(false).map(&:to_sym)
|
516
480
|
end
|
481
|
+
|
482
|
+
def assert_valid_response_body(response_body)
|
483
|
+
unless response_body.is_a?(Hash)
|
484
|
+
raise ZendeskAPI::Error::NetworkError, @response.env
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
def assert_results(results, body)
|
489
|
+
return if results
|
490
|
+
raise ZendeskAPI::Error::ClientError, "Expected #{@resource_class.model_key} or 'results' in response keys: #{body.keys.inspect}"
|
491
|
+
end
|
517
492
|
end
|
518
493
|
end
|
@@ -28,6 +28,9 @@ module ZendeskAPI
|
|
28
28
|
# @return [Symbol] Faraday adapter
|
29
29
|
attr_accessor :adapter
|
30
30
|
|
31
|
+
# @return [Proc] Faraday adapter proc
|
32
|
+
attr_accessor :adapter_proc
|
33
|
+
|
31
34
|
# @return [Boolean] Whether to allow non-HTTPS connections for development purposes.
|
32
35
|
attr_accessor :allow_http
|
33
36
|
|
data/lib/zendesk_api/error.rb
CHANGED
@@ -33,12 +33,7 @@ module ZendeskAPI
|
|
33
33
|
private
|
34
34
|
|
35
35
|
def generate_error_msg(response_body)
|
36
|
-
|
37
|
-
|
38
|
-
[
|
39
|
-
response_body["description"],
|
40
|
-
response_body["message"]
|
41
|
-
].compact.join(" - ")
|
36
|
+
response_body.values_at("description", "message", "error", "errors").compact.join(" - ")
|
42
37
|
end
|
43
38
|
end
|
44
39
|
|
data/lib/zendesk_api/helpers.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module ZendeskAPI
|
2
2
|
# @private
|
3
3
|
module Helpers
|
4
|
+
def self.present?(value)
|
5
|
+
![nil, false, "", " ", [], {}].include?(value)
|
6
|
+
end
|
7
|
+
|
4
8
|
# From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/modulize.rb
|
5
9
|
# Converts a string to module name representation.
|
6
10
|
#
|
@@ -5,11 +5,12 @@ module ZendeskAPI
|
|
5
5
|
module Response
|
6
6
|
# Faraday middleware to handle content-encoding = inflate
|
7
7
|
# @private
|
8
|
-
class Deflate < Faraday::
|
8
|
+
class Deflate < Faraday::Middleware
|
9
9
|
def on_complete(env)
|
10
|
-
if
|
11
|
-
|
12
|
-
|
10
|
+
return if env[:response_headers]['content-encoding'] != "deflate"
|
11
|
+
return if env.body.strip.empty?
|
12
|
+
|
13
|
+
env.body = Zlib::Inflate.inflate(env.body)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -7,11 +7,12 @@ module ZendeskAPI
|
|
7
7
|
# @private
|
8
8
|
module Response
|
9
9
|
# Faraday middleware to handle content-encoding = gzip
|
10
|
-
class Gzip < Faraday::
|
10
|
+
class Gzip < Faraday::Middleware
|
11
11
|
def on_complete(env)
|
12
|
-
if
|
13
|
-
|
14
|
-
|
12
|
+
return if env[:response_headers]['content-encoding'] != "gzip"
|
13
|
+
return if env[:body].force_encoding(Encoding::BINARY).strip.empty?
|
14
|
+
|
15
|
+
env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -6,7 +6,7 @@ module ZendeskAPI
|
|
6
6
|
module Response
|
7
7
|
# Parse ISO dates from response body
|
8
8
|
# @private
|
9
|
-
class ParseIsoDates < Faraday::
|
9
|
+
class ParseIsoDates < Faraday::Middleware
|
10
10
|
def call(env)
|
11
11
|
@app.call(env).on_complete do |env|
|
12
12
|
parse_dates!(env[:body])
|
@@ -3,9 +3,8 @@ module ZendeskAPI
|
|
3
3
|
module Middleware
|
4
4
|
# @private
|
5
5
|
module Response
|
6
|
-
class ParseJson < Faraday::
|
6
|
+
class ParseJson < Faraday::Middleware
|
7
7
|
CONTENT_TYPE = 'Content-Type'.freeze
|
8
|
-
dependency 'json'
|
9
8
|
|
10
9
|
def on_complete(env)
|
11
10
|
type = env[:response_headers][CONTENT_TYPE].to_s
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module ZendeskAPI
|
2
|
+
class Collection
|
3
|
+
# Contains all methods related to pagination in an attempt to slim down collection.rb
|
4
|
+
module Pagination
|
5
|
+
DEFAULT_PAGE_SIZE = 100
|
6
|
+
def more_results?(response)
|
7
|
+
Helpers.present?(response["meta"]) && response["meta"]["has_more"]
|
8
|
+
end
|
9
|
+
alias has_more_results? more_results? # For backward compatibility with 1.33.0 and 1.34.0
|
10
|
+
|
11
|
+
# Changes the per_page option. Returns self, so it can be chained. No execution.
|
12
|
+
# @return [Collection] self
|
13
|
+
def per_page(count)
|
14
|
+
clear_cache if count
|
15
|
+
@options["per_page"] = count
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Changes the page option. Returns self, so it can be chained. No execution.
|
20
|
+
# @return [Collection] self
|
21
|
+
def page(number)
|
22
|
+
clear_cache if number
|
23
|
+
@options["page"] = number
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def first_page?
|
28
|
+
!@prev_page
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_page?
|
32
|
+
!@next_page || @next_page == @query
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def page_links(body)
|
38
|
+
if body["meta"] && body["links"]
|
39
|
+
[body["links"]["next"], body["links"]["prev"]]
|
40
|
+
else
|
41
|
+
[body["next_page"], body["previous_page"]]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def cbp_response?(body)
|
46
|
+
!!(body["meta"] && body["links"])
|
47
|
+
end
|
48
|
+
|
49
|
+
def set_cbp_options
|
50
|
+
@options_per_page_was = @options.delete("per_page")
|
51
|
+
# Default to CBP by using the page param as a map
|
52
|
+
@options.page = { size: (@options_per_page_was || DEFAULT_PAGE_SIZE) }
|
53
|
+
end
|
54
|
+
|
55
|
+
# CBP requests look like: `/resources?page[size]=100`
|
56
|
+
# OBP requests look like: `/resources?page=2`
|
57
|
+
def cbp_request?
|
58
|
+
@options["page"].is_a?(Hash)
|
59
|
+
end
|
60
|
+
|
61
|
+
def intentional_obp_request?
|
62
|
+
Helpers.present?(@options["page"]) && !cbp_request?
|
63
|
+
end
|
64
|
+
|
65
|
+
def supports_cbp?
|
66
|
+
@resource_class.cbp_path_regexes.any? { |supported_path_regex| path.match?(supported_path_regex) }
|
67
|
+
end
|
68
|
+
|
69
|
+
def first_cbp_request?
|
70
|
+
# @next_page will be nil when making the first cbp request
|
71
|
+
@next_page.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def set_page_and_count(body)
|
75
|
+
@count = (body["count"] || @resources.size).to_i
|
76
|
+
@next_page, @prev_page = page_links(body)
|
77
|
+
|
78
|
+
if cbp_response?(body)
|
79
|
+
set_cbp_response_options(body)
|
80
|
+
elsif @next_page =~ /page=(\d+)/
|
81
|
+
@options["page"] = Regexp.last_match(1).to_i - 1
|
82
|
+
elsif @prev_page =~ /page=(\d+)/
|
83
|
+
@options["page"] = Regexp.last_match(1).to_i + 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def set_cbp_response_options(body)
|
88
|
+
@options.page = {} unless cbp_request?
|
89
|
+
# the line above means an intentional CBP request where page[size] is passed on the query
|
90
|
+
# this is to cater for CBP responses where we don't specify page[size] but the endpoint
|
91
|
+
# responds CBP by default. i.e `client.trigger_categories.fetch`
|
92
|
+
@options.page.merge!(
|
93
|
+
before: body["meta"]["before_cursor"],
|
94
|
+
after: body["meta"]["after_cursor"]
|
95
|
+
)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/lib/zendesk_api/resource.rb
CHANGED
@@ -39,6 +39,14 @@ module ZendeskAPI
|
|
39
39
|
def namespace(namespace)
|
40
40
|
@namespace = namespace
|
41
41
|
end
|
42
|
+
|
43
|
+
def new_from_response(client, response, includes = nil)
|
44
|
+
new(client).tap do |resource|
|
45
|
+
resource.handle_response(response)
|
46
|
+
resource.set_includes(resource, includes, response.body) if includes
|
47
|
+
resource.attributes.clear_changes
|
48
|
+
end
|
49
|
+
end
|
42
50
|
end
|
43
51
|
|
44
52
|
# @return [Hash] The resource's attributes
|
@@ -123,19 +131,16 @@ module ZendeskAPI
|
|
123
131
|
|
124
132
|
# Compares resources by class and id. If id is nil, then by object_id
|
125
133
|
def ==(other)
|
134
|
+
return false unless other
|
135
|
+
|
126
136
|
return true if other.object_id == object_id
|
127
137
|
|
128
|
-
|
129
|
-
warn "Trying to compare #{other.class} to a Resource from #{caller.first}"
|
130
|
-
end
|
138
|
+
return other.id && (other.id == id) if other.is_a?(Data)
|
131
139
|
|
132
|
-
if other.is_a?(
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
else
|
137
|
-
false
|
138
|
-
end
|
140
|
+
return id == other if other.is_a?(Integer)
|
141
|
+
|
142
|
+
warn "Trying to compare #{other.class} to a Resource
|
143
|
+
from #{caller.first}"
|
139
144
|
end
|
140
145
|
alias :eql :==
|
141
146
|
|
@@ -163,6 +168,10 @@ module ZendeskAPI
|
|
163
168
|
class DataResource < Data
|
164
169
|
attr_accessor :error, :error_message
|
165
170
|
extend Verbs
|
171
|
+
|
172
|
+
def self.cbp_path_regexes
|
173
|
+
[]
|
174
|
+
end
|
166
175
|
end
|
167
176
|
|
168
177
|
# Represents a resource that can only GET
|
@@ -24,6 +24,10 @@ module ZendeskAPI
|
|
24
24
|
|
25
25
|
class Topic < Resource
|
26
26
|
class << self
|
27
|
+
def cbp_path_regexes
|
28
|
+
[%r{^community/topics$}]
|
29
|
+
end
|
30
|
+
|
27
31
|
def resource_path
|
28
32
|
"community/topics"
|
29
33
|
end
|
@@ -83,6 +87,10 @@ module ZendeskAPI
|
|
83
87
|
def attributes_for_save
|
84
88
|
{ self.class.resource_name => [id] }
|
85
89
|
end
|
90
|
+
|
91
|
+
def self.cbp_path_regexes
|
92
|
+
[/^tags$/]
|
93
|
+
end
|
86
94
|
end
|
87
95
|
|
88
96
|
class Attachment < ReadResource
|
@@ -152,9 +160,17 @@ module ZendeskAPI
|
|
152
160
|
def self.incremental_export(client, start_time)
|
153
161
|
ZendeskAPI::Collection.new(client, self, :path => "incremental/organizations?start_time=#{start_time.to_i}")
|
154
162
|
end
|
163
|
+
|
164
|
+
def self.cbp_path_regexes
|
165
|
+
[/^organizations$/]
|
166
|
+
end
|
155
167
|
end
|
156
168
|
|
157
169
|
class Brand < Resource
|
170
|
+
def self.cbp_path_regexes
|
171
|
+
[/^brands$/]
|
172
|
+
end
|
173
|
+
|
158
174
|
def destroy!
|
159
175
|
self.active = false
|
160
176
|
save!
|
@@ -180,6 +196,10 @@ module ZendeskAPI
|
|
180
196
|
|
181
197
|
has User
|
182
198
|
has Organization
|
199
|
+
|
200
|
+
def self.cbp_path_regexes
|
201
|
+
[%r{^organizations/\d+/subscriptions$}]
|
202
|
+
end
|
183
203
|
end
|
184
204
|
|
185
205
|
class Category < Resource
|
@@ -228,6 +248,18 @@ module ZendeskAPI
|
|
228
248
|
has_many Vote
|
229
249
|
class Translation < Resource; end
|
230
250
|
has_many Translation
|
251
|
+
class Label < DataResource
|
252
|
+
include Read
|
253
|
+
include Create
|
254
|
+
include Destroy
|
255
|
+
|
256
|
+
def destroy!
|
257
|
+
super do |req|
|
258
|
+
req.path = path
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
has_many Label
|
231
263
|
end
|
232
264
|
|
233
265
|
class TopicSubscription < Resource
|
@@ -246,15 +278,19 @@ module ZendeskAPI
|
|
246
278
|
end
|
247
279
|
|
248
280
|
class Topic < Resource
|
249
|
-
has_many :subscriptions, :
|
250
|
-
has_many Tag, :
|
281
|
+
has_many :subscriptions, class: TopicSubscription, inline: true
|
282
|
+
has_many Tag, extend: Tag::Update, inline: :create
|
251
283
|
has_many Attachment
|
252
|
-
has_many :uploads, :
|
284
|
+
has_many :uploads, class: Attachment, inline: true
|
253
285
|
end
|
254
286
|
|
255
287
|
class Activity < Resource
|
256
288
|
has User
|
257
289
|
has :actor, :class => User
|
290
|
+
|
291
|
+
def self.cbp_path_regexes
|
292
|
+
[/^activities$/]
|
293
|
+
end
|
258
294
|
end
|
259
295
|
|
260
296
|
class Setting < UpdateResource
|
@@ -306,7 +342,7 @@ module ZendeskAPI
|
|
306
342
|
class Comment < DataResource
|
307
343
|
include Save
|
308
344
|
|
309
|
-
has_many :uploads, :
|
345
|
+
has_many :uploads, class: Attachment, inline: true
|
310
346
|
has :author, :class => User
|
311
347
|
|
312
348
|
def save
|
@@ -337,10 +373,18 @@ module ZendeskAPI
|
|
337
373
|
namespace 'portal'
|
338
374
|
end
|
339
375
|
|
340
|
-
class TicketField < Resource
|
376
|
+
class TicketField < Resource
|
377
|
+
def self.cbp_path_regexes
|
378
|
+
[/^ticket_fields$/]
|
379
|
+
end
|
380
|
+
end
|
341
381
|
|
342
382
|
class TicketMetric < DataResource
|
343
383
|
include Read
|
384
|
+
|
385
|
+
def self.cbp_path_regexes
|
386
|
+
[/^ticket_metrics$/]
|
387
|
+
end
|
344
388
|
end
|
345
389
|
|
346
390
|
class TicketRelated < DataResource; end
|
@@ -348,7 +392,7 @@ module ZendeskAPI
|
|
348
392
|
class TicketEvent < DataResource
|
349
393
|
class Event < Data; end
|
350
394
|
|
351
|
-
has_many :child_events, :
|
395
|
+
has_many :child_events, class: Event
|
352
396
|
has Ticket
|
353
397
|
has :updater, :class => User
|
354
398
|
|
@@ -366,6 +410,10 @@ module ZendeskAPI
|
|
366
410
|
extend UpdateMany
|
367
411
|
extend DestroyMany
|
368
412
|
|
413
|
+
def self.cbp_path_regexes
|
414
|
+
[/^tickets$/, %r{organizations/\d+/tickets}]
|
415
|
+
end
|
416
|
+
|
369
417
|
# Unlike other attributes, "comment" is not a property of the ticket,
|
370
418
|
# but is used as a "comment on save", so it should be kept unchanged,
|
371
419
|
# See https://github.com/zendesk/zendesk_api_client_rb/issues/321
|
@@ -384,13 +432,17 @@ module ZendeskAPI
|
|
384
432
|
has :author, :class => User
|
385
433
|
|
386
434
|
has_many Event
|
435
|
+
|
436
|
+
def self.cbp_path_regexes
|
437
|
+
[%r{^tickets/\d+/audits$}]
|
438
|
+
end
|
387
439
|
end
|
388
440
|
|
389
441
|
class Comment < DataResource
|
390
442
|
include Save
|
391
443
|
|
392
|
-
has_many :uploads, :
|
393
|
-
has :author, :
|
444
|
+
has_many :uploads, class: Attachment, inline: true
|
445
|
+
has :author, class: User
|
394
446
|
|
395
447
|
def save
|
396
448
|
if new_record?
|
@@ -417,35 +469,35 @@ module ZendeskAPI
|
|
417
469
|
has :submitter, :class => User
|
418
470
|
has :assignee, :class => User
|
419
471
|
|
420
|
-
has_many :collaborators, :
|
472
|
+
has_many :collaborators, class: User, inline: true, extend: (Module.new do
|
421
473
|
def to_param
|
422
474
|
map(&:id)
|
423
475
|
end
|
424
476
|
end)
|
425
477
|
|
426
478
|
has_many Audit
|
427
|
-
has :metrics, :
|
479
|
+
has :metrics, class: TicketMetric
|
428
480
|
has Group
|
429
481
|
has Organization
|
430
482
|
has Brand
|
431
|
-
has :related, :
|
483
|
+
has :related, class: TicketRelated
|
432
484
|
|
433
|
-
has Comment, :
|
485
|
+
has Comment, inline: true
|
434
486
|
has_many Comment
|
435
487
|
|
436
|
-
has :last_comment, :
|
437
|
-
has_many :last_comments, :
|
488
|
+
has :last_comment, class: Comment, inline: true
|
489
|
+
has_many :last_comments, class: Comment, inline: true
|
438
490
|
|
439
|
-
has_many Tag, :
|
491
|
+
has_many Tag, extend: Tag::Update, inline: :create
|
440
492
|
|
441
|
-
has_many :incidents, :
|
493
|
+
has_many :incidents, class: Ticket
|
442
494
|
|
443
495
|
# Gets a incremental export of tickets from the start_time until now.
|
444
496
|
# @param [Client] client The {Client} object to be used
|
445
497
|
# @param [Integer] start_time The start_time parameter
|
446
498
|
# @return [Collection] Collection of {Ticket}
|
447
499
|
def self.incremental_export(client, start_time)
|
448
|
-
ZendeskAPI::Collection.new(client, self, :
|
500
|
+
ZendeskAPI::Collection.new(client, self, path: "incremental/tickets?start_time=#{start_time.to_i}")
|
449
501
|
end
|
450
502
|
|
451
503
|
# Imports a ticket through the imports/tickets endpoint using save!
|
@@ -454,7 +506,7 @@ module ZendeskAPI
|
|
454
506
|
# @return [Ticket] Created object or nil
|
455
507
|
def self.import!(client, attributes)
|
456
508
|
new(client, attributes).tap do |ticket|
|
457
|
-
ticket.save!(:
|
509
|
+
ticket.save!(path: "imports/tickets")
|
458
510
|
end
|
459
511
|
end
|
460
512
|
|
@@ -464,7 +516,7 @@ module ZendeskAPI
|
|
464
516
|
# @return [Ticket] Created object or nil
|
465
517
|
def self.import(client, attributes)
|
466
518
|
ticket = new(client, attributes)
|
467
|
-
return unless ticket.save(:
|
519
|
+
return unless ticket.save(path: "imports/tickets")
|
468
520
|
ticket
|
469
521
|
end
|
470
522
|
end
|
@@ -474,6 +526,10 @@ module ZendeskAPI
|
|
474
526
|
|
475
527
|
# Recovers this suspended ticket to an actual ticket
|
476
528
|
put :recover
|
529
|
+
|
530
|
+
def self.cbp_path_regexes
|
531
|
+
[/^suspended_tickets$/]
|
532
|
+
end
|
477
533
|
end
|
478
534
|
|
479
535
|
class DeletedTicket < ReadResource
|
@@ -483,6 +539,10 @@ module ZendeskAPI
|
|
483
539
|
# Restores this previously deleted ticket to an actual ticket
|
484
540
|
put :restore
|
485
541
|
put :restore_many
|
542
|
+
|
543
|
+
def self.cbp_path_regexes
|
544
|
+
[/^deleted_tickets$/]
|
545
|
+
end
|
486
546
|
end
|
487
547
|
|
488
548
|
class UserViewRow < DataResource
|
@@ -498,9 +558,9 @@ module ZendeskAPI
|
|
498
558
|
# @internal Optional columns
|
499
559
|
|
500
560
|
has Group
|
501
|
-
has :assignee, :
|
502
|
-
has :requester, :
|
503
|
-
has :submitter, :
|
561
|
+
has :assignee, class: User
|
562
|
+
has :requester, class: User
|
563
|
+
has :submitter, class: User
|
504
564
|
has Organization
|
505
565
|
|
506
566
|
def self.model_key
|
@@ -580,6 +640,10 @@ module ZendeskAPI
|
|
580
640
|
def self.preview(client, options = {})
|
581
641
|
Collection.new(client, ViewRow, options.merge(:path => "views/preview", :verb => :post))
|
582
642
|
end
|
643
|
+
|
644
|
+
def self.cbp_path_regexes
|
645
|
+
[/^views$/]
|
646
|
+
end
|
583
647
|
end
|
584
648
|
|
585
649
|
class Trigger < Rule
|
@@ -587,6 +651,10 @@ module ZendeskAPI
|
|
587
651
|
include Actions
|
588
652
|
|
589
653
|
has :execution, :class => RuleExecution
|
654
|
+
|
655
|
+
def self.cbp_path_regexes
|
656
|
+
[/^triggers$/, %r{^triggers/active$}]
|
657
|
+
end
|
590
658
|
end
|
591
659
|
|
592
660
|
class Automation < Rule
|
@@ -594,6 +662,10 @@ module ZendeskAPI
|
|
594
662
|
include Actions
|
595
663
|
|
596
664
|
has :execution, :class => RuleExecution
|
665
|
+
|
666
|
+
def self.cbp_path_regexes
|
667
|
+
[/^automations$/]
|
668
|
+
end
|
597
669
|
end
|
598
670
|
|
599
671
|
class Macro < Rule
|
@@ -601,6 +673,10 @@ module ZendeskAPI
|
|
601
673
|
|
602
674
|
has :execution, :class => RuleExecution
|
603
675
|
|
676
|
+
def self.cbp_path_regexes
|
677
|
+
[/^macros$/]
|
678
|
+
end
|
679
|
+
|
604
680
|
# Returns the update to a ticket that happens when a macro will be applied.
|
605
681
|
# @param [Ticket] ticket Optional {Ticket} to apply this macro to.
|
606
682
|
# @raise [Faraday::ClientError] Raised for any non-200 response.
|
@@ -636,6 +712,18 @@ module ZendeskAPI
|
|
636
712
|
|
637
713
|
has User
|
638
714
|
has Group
|
715
|
+
|
716
|
+
def self.cbp_path_regexes
|
717
|
+
[%r{^groups/\d+/memberships$}]
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
class Group < Resource
|
722
|
+
has_many :memberships, class: GroupMembership, path: "memberships"
|
723
|
+
|
724
|
+
def self.cbp_path_regexes
|
725
|
+
[/^groups$/, %r{^groups/assignable$}]
|
726
|
+
end
|
639
727
|
end
|
640
728
|
|
641
729
|
class User < Resource
|
@@ -660,6 +748,10 @@ module ZendeskAPI
|
|
660
748
|
put :request_verification
|
661
749
|
end
|
662
750
|
|
751
|
+
def self.cbp_path_regexes
|
752
|
+
[/^users$/, %r{^organizations/\d+/users$}]
|
753
|
+
end
|
754
|
+
|
663
755
|
any :password
|
664
756
|
|
665
757
|
# Set a user's password
|
@@ -777,6 +869,10 @@ module ZendeskAPI
|
|
777
869
|
def self.singular_resource_name
|
778
870
|
"client"
|
779
871
|
end
|
872
|
+
|
873
|
+
def self.cbp_path_regexes
|
874
|
+
[%r{^oauth/clients$}]
|
875
|
+
end
|
780
876
|
end
|
781
877
|
|
782
878
|
class OauthToken < ReadResource
|
data/lib/zendesk_api/search.rb
CHANGED
data/lib/zendesk_api/verbs.rb
CHANGED
@@ -44,14 +44,12 @@ module ZendeskAPI
|
|
44
44
|
end
|
45
45
|
|
46
46
|
define_method method do |*method_args|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
false
|
54
|
-
end
|
47
|
+
send("#{method}!", *method_args)
|
48
|
+
rescue ZendeskAPI::Error::RecordInvalid => e
|
49
|
+
@errors = e.errors
|
50
|
+
false
|
51
|
+
rescue ZendeskAPI::Error::ClientError
|
52
|
+
false
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
data/lib/zendesk_api/version.rb
CHANGED
data/lib/zendesk_api.rb
CHANGED
metadata
CHANGED
@@ -1,36 +1,44 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Davidovitz
|
8
8
|
- Michael Grosser
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-09-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - "
|
19
|
-
- !ruby/object:Gem::Version
|
20
|
-
version: 0.9.0
|
21
|
-
- - "<"
|
18
|
+
- - ">"
|
22
19
|
- !ruby/object:Gem::Version
|
23
20
|
version: 2.0.0
|
24
21
|
type: :runtime
|
25
22
|
prerelease: false
|
26
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 2.0.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: faraday-multipart
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
27
31
|
requirements:
|
28
32
|
- - ">="
|
29
33
|
- !ruby/object:Gem::Version
|
30
|
-
version: 0
|
31
|
-
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
41
|
+
version: '0'
|
34
42
|
- !ruby/object:Gem::Dependency
|
35
43
|
name: hashie
|
36
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,6 +136,7 @@ files:
|
|
128
136
|
- lib/zendesk_api/middleware/response/parse_json.rb
|
129
137
|
- lib/zendesk_api/middleware/response/raise_error.rb
|
130
138
|
- lib/zendesk_api/middleware/response/sanitize_response.rb
|
139
|
+
- lib/zendesk_api/pagination.rb
|
131
140
|
- lib/zendesk_api/resource.rb
|
132
141
|
- lib/zendesk_api/resources.rb
|
133
142
|
- lib/zendesk_api/search.rb
|
@@ -144,11 +153,11 @@ licenses:
|
|
144
153
|
- Apache-2.0
|
145
154
|
metadata:
|
146
155
|
bug_tracker_uri: https://github.com/zendesk/zendesk_api_client_rb/issues
|
147
|
-
changelog_uri: https://github.com/zendesk/zendesk_api_client_rb/blob/
|
148
|
-
documentation_uri: https://www.rubydoc.info/gems/zendesk_api/
|
149
|
-
source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/
|
156
|
+
changelog_uri: https://github.com/zendesk/zendesk_api_client_rb/blob/v3.0.5/CHANGELOG.md
|
157
|
+
documentation_uri: https://www.rubydoc.info/gems/zendesk_api/3.0.5
|
158
|
+
source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/v3.0.5
|
150
159
|
wiki_uri: https://github.com/zendesk/zendesk_api_client_rb/wiki
|
151
|
-
post_install_message:
|
160
|
+
post_install_message:
|
152
161
|
rdoc_options: []
|
153
162
|
require_paths:
|
154
163
|
- lib
|
@@ -156,15 +165,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
165
|
requirements:
|
157
166
|
- - ">="
|
158
167
|
- !ruby/object:Gem::Version
|
159
|
-
version: '2.
|
168
|
+
version: '2.7'
|
160
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
170
|
requirements:
|
162
171
|
- - ">="
|
163
172
|
- !ruby/object:Gem::Version
|
164
173
|
version: 1.3.6
|
165
174
|
requirements: []
|
166
|
-
rubygems_version: 3.0.3
|
167
|
-
signing_key:
|
175
|
+
rubygems_version: 3.0.3.1
|
176
|
+
signing_key:
|
168
177
|
specification_version: 4
|
169
178
|
summary: Zendesk REST API Client
|
170
179
|
test_files: []
|