zendesk_api 1.37.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []