zendesk_api 1.37.0 → 3.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c5a2ced45e0201f6f9a45e5b8f7cf6951ca92c15ce893283c2289d0b260dc77
4
- data.tar.gz: 31fa7566865e7191f49dadf6a5e01573264f4fc62ddfd4f635f8f7edd4be9ab2
3
+ metadata.gz: bb7a7899050cd837be40995be562bb7c95a04e7d631a34cdddaa671c1eeca9b3
4
+ data.tar.gz: c042f01365e91e868c54e7aa5fc1318fc490efa2440093e24df86df6800feaba
5
5
  SHA512:
6
- metadata.gz: a1b355c67c8126f69f32ff6cd24d03b81b75eec27a0a72044383d0e06a871ba5bd18778119523a013725162048393d7a6bf58f075013e852303255b78bccb73f
7
- data.tar.gz: 78ecdd8fd4d2fd889df06aea1ac98df7c68e6f89378f1358594b30853b23b3179f304ee4d87a781bda0047bc1970b8c28dfd147907d74223e28ffceb1676d1b1
6
+ metadata.gz: efafbaa0881befe0fd827e9fa465a3f7be19ec566199dd1640f5bba68ec101a6a0eb8b30efe850a08ca5f2adc2004ab809e74ba96eb52b3f8ac2e63f75c07e72
7
+ data.tar.gz: 6c81354976ef9ce6adf2f6ae084d7a60ae04fd49e10033e5025e5697a1f7adaac9385834f1c22a671e08cb94c3132d5c365a2e2a969b42f3035e301e94ed0a68
@@ -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
- raise "Resource for #{method} does not exist" unless method_as_class(method)
45
- return ZendeskAPI::Collection.new(self, method_as_class(method), options)
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] ||= method_as_class(method)
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
- ((cache = @resource_cache[method]) && cache[:class]) || !method_as_class(method).nil? || super
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
- # request
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
- builder.use ZendeskAPI::Middleware::Request::Retry, :logger => config.logger, :retry_codes => config.retry_codes, :retry_on_exception => config.retry_on_exception if config.retry
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 method_as_class(method)
196
- klass_as_string = ZendeskAPI::Helpers.modulize_string(Inflection.singular(method.to_s.gsub(/\W/, '')))
197
- ZendeskAPI::Association.class_from_namespace(klass_as_string)
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
- @resources
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"] += 1
226
+ @options["page"] = @options["page"].to_i + 1
258
227
  elsif (@query = @next_page)
228
+ # Send _only_ url param "?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 @options["page"] && @options["page"] > 1
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 "?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 = get_response_body(link)
306
+ response = @client.connection.send("get", link).body
343
307
 
344
- original_response_body["results"] = original_response_body["results"] + response["results"]
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 set_page_and_count(body)
355
- @count = (body["count"] || @resources.size).to_i
356
- @next_page, @prev_page = body["next_page"], body["previous_page"]
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
- if @next_page =~ /page=(\d+)/
359
- @options["page"] = $1.to_i - 1
360
- elsif @prev_page =~ /page=(\d+)/
361
- @options["page"] = $1.to_i + 1
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
- arguments = [resource, @options["page"] || 1]
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
- @response = @client.connection.send(@verb || "get", path) do |req|
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 handle_cursor_response(response_body)
439
- unless response_body.is_a?(Hash)
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
- unless results
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
- unless response_body.is_a?(Hash)
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
- unless results
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 => @collection_path.dup.push(name))
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
 
@@ -33,12 +33,7 @@ module ZendeskAPI
33
33
  private
34
34
 
35
35
  def generate_error_msg(response_body)
36
- return unless response_body["description"] || response_body["message"]
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
 
@@ -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
  #
@@ -6,7 +6,6 @@ module ZendeskAPI
6
6
  class EncodeJson < Faraday::Middleware
7
7
  CONTENT_TYPE = 'Content-Type'.freeze
8
8
  MIME_TYPE = 'application/json'.freeze
9
- dependency 'json'
10
9
 
11
10
  def call(env)
12
11
  type = env[:request_headers][CONTENT_TYPE].to_s
@@ -4,7 +4,7 @@ module ZendeskAPI
4
4
  module Middleware
5
5
  module Response
6
6
  # @private
7
- class Callback < Faraday::Response::Middleware
7
+ class Callback < Faraday::Middleware
8
8
  def initialize(app, client)
9
9
  super(app)
10
10
  @client = client
@@ -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::Response::Middleware
8
+ class Deflate < Faraday::Middleware
9
9
  def on_complete(env)
10
- if !env.body.strip.empty? && env[:response_headers]['content-encoding'] == "deflate"
11
- env.body = Zlib::Inflate.inflate(env.body)
12
- end
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::Response::Middleware
10
+ class Gzip < Faraday::Middleware
11
11
  def on_complete(env)
12
- if !env[:body].strip.empty? && env[:response_headers]['content-encoding'] == "gzip"
13
- env[:body] = Zlib::GzipReader.new(StringIO.new(env[:body])).read
14
- end
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::Response::Middleware
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::Response::Middleware
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
@@ -1,7 +1,7 @@
1
1
  module ZendeskAPI
2
2
  module Middleware
3
3
  module Response
4
- class SanitizeResponse < Faraday::Response::Middleware
4
+ class SanitizeResponse < Faraday::Middleware
5
5
  def on_complete(env)
6
6
  env[:body].scrub!('')
7
7
  end
@@ -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
@@ -163,6 +163,10 @@ module ZendeskAPI
163
163
  class DataResource < Data
164
164
  attr_accessor :error, :error_message
165
165
  extend Verbs
166
+
167
+ def self.cbp_path_regexes
168
+ []
169
+ end
166
170
  end
167
171
 
168
172
  # Represents a resource that can only GET
@@ -152,6 +152,10 @@ module ZendeskAPI
152
152
  def self.incremental_export(client, start_time)
153
153
  ZendeskAPI::Collection.new(client, self, :path => "incremental/organizations?start_time=#{start_time.to_i}")
154
154
  end
155
+
156
+ def self.cbp_path_regexes
157
+ [/organizations$/]
158
+ end
155
159
  end
156
160
 
157
161
  class Brand < Resource
@@ -180,6 +184,10 @@ module ZendeskAPI
180
184
 
181
185
  has User
182
186
  has Organization
187
+
188
+ def self.cbp_path_regexes
189
+ [%r{organizations/\d+/subscriptions$}]
190
+ end
183
191
  end
184
192
 
185
193
  class Category < Resource
@@ -228,6 +236,18 @@ module ZendeskAPI
228
236
  has_many Vote
229
237
  class Translation < Resource; end
230
238
  has_many Translation
239
+ class Label < DataResource
240
+ include Read
241
+ include Create
242
+ include Destroy
243
+
244
+ def destroy!
245
+ super do |req|
246
+ req.path = path
247
+ end
248
+ end
249
+ end
250
+ has_many Label
231
251
  end
232
252
 
233
253
  class TopicSubscription < Resource
@@ -246,10 +266,10 @@ module ZendeskAPI
246
266
  end
247
267
 
248
268
  class Topic < Resource
249
- has_many :subscriptions, :class => TopicSubscription, :inline => true
250
- has_many Tag, :extend => Tag::Update, :inline => :create
269
+ has_many :subscriptions, class: TopicSubscription, inline: true
270
+ has_many Tag, extend: Tag::Update, inline: :create
251
271
  has_many Attachment
252
- has_many :uploads, :class => Attachment, :inline => true
272
+ has_many :uploads, class: Attachment, inline: true
253
273
  end
254
274
 
255
275
  class Activity < Resource
@@ -306,7 +326,7 @@ module ZendeskAPI
306
326
  class Comment < DataResource
307
327
  include Save
308
328
 
309
- has_many :uploads, :class => Attachment, :inline => true
329
+ has_many :uploads, class: Attachment, inline: true
310
330
  has :author, :class => User
311
331
 
312
332
  def save
@@ -348,7 +368,7 @@ module ZendeskAPI
348
368
  class TicketEvent < DataResource
349
369
  class Event < Data; end
350
370
 
351
- has_many :child_events, :class => Event
371
+ has_many :child_events, class: Event
352
372
  has Ticket
353
373
  has :updater, :class => User
354
374
 
@@ -366,6 +386,10 @@ module ZendeskAPI
366
386
  extend UpdateMany
367
387
  extend DestroyMany
368
388
 
389
+ def self.cbp_path_regexes
390
+ [/tickets$/]
391
+ end
392
+
369
393
  # Unlike other attributes, "comment" is not a property of the ticket,
370
394
  # but is used as a "comment on save", so it should be kept unchanged,
371
395
  # See https://github.com/zendesk/zendesk_api_client_rb/issues/321
@@ -389,8 +413,8 @@ module ZendeskAPI
389
413
  class Comment < DataResource
390
414
  include Save
391
415
 
392
- has_many :uploads, :class => Attachment, :inline => true
393
- has :author, :class => User
416
+ has_many :uploads, class: Attachment, inline: true
417
+ has :author, class: User
394
418
 
395
419
  def save
396
420
  if new_record?
@@ -417,35 +441,35 @@ module ZendeskAPI
417
441
  has :submitter, :class => User
418
442
  has :assignee, :class => User
419
443
 
420
- has_many :collaborators, :class => User, :inline => true, :extend => (Module.new do
444
+ has_many :collaborators, class: User, inline: true, extend: (Module.new do
421
445
  def to_param
422
446
  map(&:id)
423
447
  end
424
448
  end)
425
449
 
426
450
  has_many Audit
427
- has :metrics, :class => TicketMetric
451
+ has :metrics, class: TicketMetric
428
452
  has Group
429
453
  has Organization
430
454
  has Brand
431
- has :related, :class => TicketRelated
455
+ has :related, class: TicketRelated
432
456
 
433
- has Comment, :inline => true
457
+ has Comment, inline: true
434
458
  has_many Comment
435
459
 
436
- has :last_comment, :class => Comment, :inline => true
437
- has_many :last_comments, :class => Comment, :inline => true
460
+ has :last_comment, class: Comment, inline: true
461
+ has_many :last_comments, class: Comment, inline: true
438
462
 
439
- has_many Tag, :extend => Tag::Update, :inline => :create
463
+ has_many Tag, extend: Tag::Update, inline: :create
440
464
 
441
- has_many :incidents, :class => Ticket
465
+ has_many :incidents, class: Ticket
442
466
 
443
467
  # Gets a incremental export of tickets from the start_time until now.
444
468
  # @param [Client] client The {Client} object to be used
445
469
  # @param [Integer] start_time The start_time parameter
446
470
  # @return [Collection] Collection of {Ticket}
447
471
  def self.incremental_export(client, start_time)
448
- ZendeskAPI::Collection.new(client, self, :path => "incremental/tickets?start_time=#{start_time.to_i}")
472
+ ZendeskAPI::Collection.new(client, self, path: "incremental/tickets?start_time=#{start_time.to_i}")
449
473
  end
450
474
 
451
475
  # Imports a ticket through the imports/tickets endpoint using save!
@@ -454,7 +478,7 @@ module ZendeskAPI
454
478
  # @return [Ticket] Created object or nil
455
479
  def self.import!(client, attributes)
456
480
  new(client, attributes).tap do |ticket|
457
- ticket.save!(:path => "imports/tickets")
481
+ ticket.save!(path: "imports/tickets")
458
482
  end
459
483
  end
460
484
 
@@ -464,7 +488,7 @@ module ZendeskAPI
464
488
  # @return [Ticket] Created object or nil
465
489
  def self.import(client, attributes)
466
490
  ticket = new(client, attributes)
467
- return unless ticket.save(:path => "imports/tickets")
491
+ return unless ticket.save(path: "imports/tickets")
468
492
  ticket
469
493
  end
470
494
  end
@@ -498,9 +522,9 @@ module ZendeskAPI
498
522
  # @internal Optional columns
499
523
 
500
524
  has Group
501
- has :assignee, :class => User
502
- has :requester, :class => User
503
- has :submitter, :class => User
525
+ has :assignee, class: User
526
+ has :requester, class: User
527
+ has :submitter, class: User
504
528
  has Organization
505
529
 
506
530
  def self.model_key
@@ -587,6 +611,10 @@ module ZendeskAPI
587
611
  include Actions
588
612
 
589
613
  has :execution, :class => RuleExecution
614
+
615
+ def self.cbp_path_regexes
616
+ [/triggers$/, %r{triggers/active$}]
617
+ end
590
618
  end
591
619
 
592
620
  class Automation < Rule
@@ -636,6 +664,18 @@ module ZendeskAPI
636
664
 
637
665
  has User
638
666
  has Group
667
+
668
+ def self.cbp_path_regexes
669
+ [%r{groups/\d+/memberships$}]
670
+ end
671
+ end
672
+
673
+ class Group < Resource
674
+ has_many :memberships, class: GroupMembership, path: "memberships"
675
+
676
+ def self.cbp_path_regexes
677
+ [/groups$/, %r{groups/assignable$}]
678
+ end
639
679
  end
640
680
 
641
681
  class User < Resource
@@ -25,6 +25,10 @@ module ZendeskAPI
25
25
  (klass || Result).new(client, attributes)
26
26
  end
27
27
 
28
+ def self.cbp_path_regexes
29
+ []
30
+ end
31
+
28
32
  class Result < Data; end
29
33
 
30
34
  class << self
@@ -44,14 +44,12 @@ module ZendeskAPI
44
44
  end
45
45
 
46
46
  define_method method do |*method_args|
47
- begin
48
- send("#{method}!", *method_args)
49
- rescue ZendeskAPI::Error::RecordInvalid => e
50
- @errors = e.errors
51
- false
52
- rescue ZendeskAPI::Error::ClientError
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
@@ -1,3 +1,3 @@
1
1
  module ZendeskAPI
2
- VERSION = "1.37.0"
2
+ VERSION = "3.0.2"
3
3
  end
data/lib/zendesk_api.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  module ZendeskAPI; end
2
2
 
3
+ require 'faraday'
4
+ require 'faraday/multipart'
5
+
6
+ require 'zendesk_api/helpers'
3
7
  require 'zendesk_api/core_ext/inflection'
4
8
  require 'zendesk_api/client'
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: 1.37.0
4
+ version: 3.0.2
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: 2022-09-07 00:00:00.000000000 Z
12
+ date: 2023-08-01 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.9.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: 2.0.0
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/v1.37.0/CHANGELOG.md
148
- documentation_uri: https://www.rubydoc.info/gems/zendesk_api/1.37.0
149
- source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/v1.37.0
156
+ changelog_uri: https://github.com/zendesk/zendesk_api_client_rb/blob/v3.0.2/CHANGELOG.md
157
+ documentation_uri: https://www.rubydoc.info/gems/zendesk_api/3.0.2
158
+ source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/v3.0.2
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.3'
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: []