zendesk_api 1.31.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5effe63f9bf20a2f1609678307075c1469cb10bf73ddf992bac282fe0373643e
4
- data.tar.gz: 528b5448a9add09ae4f14dac496dff8753ea6ea80e991f5610d021ec70fa27de
3
+ metadata.gz: 1cb0a6ce03a083efc37a6f742e90e58955a411ce76c3bfffb78ad5fc61f336b6
4
+ data.tar.gz: 10d25156b4961da61e2c1b7276ef5a8e4a17664c93d4a24e8f466ec9dc2e85b1
5
5
  SHA512:
6
- metadata.gz: e8897e7999a22d4c0785696fcfd59310035eb4f654cbbbfbde1b0f4be72defe5a106bf4489c1bef71b4638cfc8d04f0d6866503f47c928c4c9ed7275aa14b77a
7
- data.tar.gz: 1a8c38c9297aa2220b9d46909be86bcc2de2572bc11b43a4fa56a4f7ff7bed1516af0eda2a0040fb3e4d8ad8b50c3a8929b420e5dcd7b833c1f4893f44eeb0f1
6
+ metadata.gz: da965fc1a9d28cb7edafdb82a56a1e73b64930f7706ac32bc9980ee3da415e540362f036c8dd6101b7615ce3781e4cc9e5645780bd83c504c714c60879450dcc
7
+ data.tar.gz: edbee03ff02ea28e78f88c9e1766d0cccbd0d59b068ae103f80d9c83f10cf734707e96a3341710131f93ffc346066f04a0e3d0200cc9def631cb984285086679
@@ -19,13 +19,8 @@ module ZendeskAPI
19
19
  nil
20
20
  end
21
21
 
22
- # 1.9+ changed default to search ancestors, added flag to disable behavior.
23
22
  def module_defines_class?(mod, klass_as_string)
24
- if RUBY_VERSION < '1.9'
25
- mod.const_defined?(klass_as_string)
26
- else
27
- mod.const_defined?(klass_as_string, false)
28
- end
23
+ mod.const_defined?(klass_as_string, false)
29
24
  end
30
25
  end
31
26
 
@@ -58,7 +53,6 @@ module ZendeskAPI
58
53
 
59
54
  namespace = @options[:class].to_s.split("::")
60
55
  namespace[-1] = @options[:class].resource_path
61
-
62
56
  # Remove components without path information
63
57
  ignorable_namespace_strings.each { |ns| namespace.delete(ns) }
64
58
  has_parent = namespace.size > 1 || (options[:with_parent] && @options.parent)
@@ -181,7 +181,7 @@ module ZendeskAPI
181
181
  builder.use ZendeskAPI::Middleware::Request::EncodeJson
182
182
 
183
183
  # Should always be first in the stack
184
- builder.use ZendeskAPI::Middleware::Request::Retry, :logger => config.logger if config.retry
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
185
185
  if config.raise_error_when_rate_limited
186
186
  builder.use ZendeskAPI::Middleware::Request::RaiseRateLimited, :logger => config.logger
187
187
  end
@@ -198,7 +198,7 @@ module ZendeskAPI
198
198
  end
199
199
 
200
200
  def check_url
201
- if !config.allow_http && config.url !~ /^https/
201
+ if !config.allow_http && !config.url.start_with?('https://')
202
202
  raise ArgumentError, "zendesk_api is ssl only; url must begin with https://"
203
203
  end
204
204
  end
@@ -1,5 +1,6 @@
1
1
  require 'zendesk_api/resource'
2
2
  require 'zendesk_api/resources'
3
+ require 'zendesk_api/search'
3
4
 
4
5
  module ZendeskAPI
5
6
  # Represents a collection of resources. Lazily loaded, resources aren't
@@ -28,7 +29,7 @@ module ZendeskAPI
28
29
  # @param [String] resource The resource being collected.
29
30
  # @param [Hash] options Any additional options to be passed in.
30
31
  def initialize(client, resource, options = {})
31
- @client, @resource_class, @resource = client, resource, resource.resource_name
32
+ @client, @resource_class, @resource = client, resource, resource.resource_path
32
33
  @options = SilentMash.new(options)
33
34
 
34
35
  set_association_from_options
@@ -47,7 +48,7 @@ module ZendeskAPI
47
48
  end
48
49
 
49
50
  # Methods that take a Hash argument
50
- methods = %w{create find update update_many destroy}
51
+ methods = %w{create find update update_many destroy create_or_update}
51
52
  methods += methods.map { |method| method + "!" }
52
53
  methods.each do |deferrable|
53
54
  # Passes arguments and the proper path to the resource class method.
@@ -185,9 +186,15 @@ module ZendeskAPI
185
186
  elsif association && association.options.parent && association.options.parent.new_record?
186
187
  return (@resources = [])
187
188
  end
189
+ path_query_link = (@query || path)
188
190
 
189
- @response = get_response(@query || path)
190
- handle_response(@response.body)
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
191
198
 
192
199
  @resources
193
200
  end
@@ -248,7 +255,7 @@ module ZendeskAPI
248
255
  if @options["page"]
249
256
  clear_cache
250
257
  @options["page"] += 1
251
- elsif @query = @next_page
258
+ elsif (@query = @next_page)
252
259
  fetch(true)
253
260
  else
254
261
  clear_cache
@@ -264,7 +271,7 @@ module ZendeskAPI
264
271
  if @options["page"] && @options["page"] > 1
265
272
  clear_cache
266
273
  @options["page"] -= 1
267
- elsif @query = @prev_page
274
+ elsif (@query = @prev_page)
268
275
  fetch(true)
269
276
  else
270
277
  clear_cache
@@ -313,12 +320,35 @@ module ZendeskAPI
313
320
  end
314
321
  end
315
322
 
316
- alias :to_str :to_s
323
+ alias to_str to_s
317
324
 
318
325
  def to_param
319
326
  map(&:to_param)
320
327
  end
321
328
 
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
+ def get_next_page_data(original_response_body)
339
+ link = original_response_body["links"]["next"]
340
+
341
+ while link
342
+ response = get_response_body(link)
343
+
344
+ original_response_body["results"] = original_response_body["results"] + response["results"]
345
+
346
+ link = response["meta"]["has_more"] ? response["links"]["next"] : nil
347
+ end
348
+
349
+ original_response_body
350
+ end
351
+
322
352
  private
323
353
 
324
354
  def set_page_and_count(body)
@@ -372,8 +402,6 @@ module ZendeskAPI
372
402
  result
373
403
  end
374
404
 
375
- ## Initialize
376
-
377
405
  def join_special_params
378
406
  # some params use comma-joined strings instead of query-based arrays for multiple values
379
407
  @options.each do |k, v|
@@ -389,7 +417,6 @@ module ZendeskAPI
389
417
  association_options = { :path => @options.delete(:path) }
390
418
  association_options[:path] ||= @collection_path.join("/") if @collection_path
391
419
  @association = @options.delete(:association) || Association.new(association_options.merge(:class => @resource_class))
392
-
393
420
  @collection_path ||= [@resource]
394
421
  end
395
422
 
@@ -410,6 +437,25 @@ module ZendeskAPI
410
437
  end
411
438
  end
412
439
 
440
+ def handle_cursor_response(response_body)
441
+ unless response_body.is_a?(Hash)
442
+ raise ZendeskAPI::Error::NetworkError, @response.env
443
+ end
444
+
445
+ response_body = get_next_page_data(response_body) if more_results?(response_body)
446
+
447
+ body = response_body.dup
448
+ results = body.delete(@resource_class.model_key) || body.delete("results")
449
+
450
+ unless results
451
+ raise ZendeskAPI::Error::ClientError, "Expected #{@resource_class.model_key} or 'results' in response keys: #{body.keys.inspect}"
452
+ end
453
+
454
+ @resources = results.map do |res|
455
+ wrap_resource(res)
456
+ end
457
+ end
458
+
413
459
  def handle_response(response_body)
414
460
  unless response_body.is_a?(Hash)
415
461
  raise ZendeskAPI::Error::NetworkError, @response.env
@@ -45,6 +45,12 @@ module ZendeskAPI
45
45
  # @return [Boolean] Whether to use resource_cache or not
46
46
  attr_accessor :use_resource_cache
47
47
 
48
+ # specify the server error codes in which you want a retry to be attempted
49
+ attr_accessor :retry_codes
50
+
51
+ # specify if you want a (network layer) exception to elicit a retry
52
+ attr_accessor :retry_on_exception
53
+
48
54
  def initialize
49
55
  @client_options = {}
50
56
  @use_resource_cache = true
@@ -20,7 +20,7 @@ module ZendeskAPI
20
20
  super
21
21
 
22
22
  if response[:body].is_a?(Hash)
23
- @errors = response[:body]["details"] || response[:body]["description"]
23
+ @errors = response[:body]["details"] || generate_error_msg(response[:body])
24
24
  end
25
25
 
26
26
  @errors ||= {}
@@ -29,6 +29,17 @@ module ZendeskAPI
29
29
  def to_s
30
30
  "#{self.class.name}: #{@errors}"
31
31
  end
32
+
33
+ private
34
+
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(" - ")
42
+ end
32
43
  end
33
44
 
34
45
  class NetworkError < ClientError; end
@@ -2,6 +2,19 @@ module ZendeskAPI
2
2
  # @private
3
3
  module Helpers
4
4
  # From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/modulize.rb
5
+ # Converts a string to module name representation.
6
+ #
7
+ # This is essentially #camelcase, but it also converts
8
+ # '/' to '::' which is useful for converting paths to
9
+ # namespaces.
10
+ #
11
+ # Examples
12
+ #
13
+ # "method_name".modulize #=> "MethodName"
14
+ # "method/name".modulize #=> "Method::Name"
15
+ #
16
+ # @param string [string] input, `module/class_name`
17
+ # @return [string] a string that can become a class, `Module::ClassName`
5
18
  def self.modulize_string(string)
6
19
  # gsub('__','/'). # why was this ever here?
7
20
  string.gsub(/__(.?)/) { "::#{$1.upcase}" }.
@@ -11,6 +24,14 @@ module ZendeskAPI
11
24
  end
12
25
 
13
26
  # From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb
27
+ # Underscore a string such that camelcase, dashes and spaces are
28
+ # replaced by underscores. This is the reverse of {#camelcase},
29
+ # albeit not an exact inverse.
30
+ #
31
+ # "SnakeCase".snakecase #=> "snake_case"
32
+ # "Snake-Case".snakecase #=> "snake_case"
33
+ # "Snake Case".snakecase #=> "snake_case"
34
+ # "Snake - Case".snakecase #=> "snake_case"
14
35
  def self.snakecase_string(string)
15
36
  # gsub(/::/, '/').
16
37
  string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
@@ -1,5 +1,4 @@
1
1
  require "faraday/middleware"
2
-
3
2
  module ZendeskAPI
4
3
  module Middleware
5
4
  # @private
@@ -8,19 +7,37 @@ module ZendeskAPI
8
7
  # @private
9
8
  class Retry < Faraday::Middleware
10
9
  DEFAULT_RETRY_AFTER = 10
11
- ERROR_CODES = [429, 503]
10
+ DEFAULT_ERROR_CODES = [429, 503]
12
11
 
13
12
  def initialize(app, options = {})
14
13
  super(app)
15
14
  @logger = options[:logger]
15
+ @error_codes = options.key?(:retry_codes) && options[:retry_codes] ? options[:retry_codes] : DEFAULT_ERROR_CODES
16
+ @retry_on_exception = options.key?(:retry_on_exception) && options[:retry_on_exception] ? options[:retry_on_exception] : false
16
17
  end
17
18
 
18
19
  def call(env)
19
20
  original_env = env.dup
20
- response = @app.call(env)
21
+ exception_happened = false
22
+ if @retry_on_exception
23
+ begin
24
+ response = @app.call(env)
25
+ rescue StandardError => e
26
+ exception_happened = true
27
+ end
28
+ else
29
+ response = @app.call(env)
30
+ end
31
+
32
+ if exception_happened || @error_codes.include?(response.env[:status])
33
+
34
+ if exception_happened
35
+ seconds_left = DEFAULT_RETRY_AFTER.to_i
36
+ @logger.warn "An exception happened, waiting #{seconds_left} seconds... #{e}" if @logger
37
+ else
38
+ seconds_left = (response.env[:response_headers][:retry_after] || DEFAULT_RETRY_AFTER).to_i
39
+ end
21
40
 
22
- if ERROR_CODES.include?(response.env[:status])
23
- seconds_left = (response.env[:response_headers][:retry_after] || DEFAULT_RETRY_AFTER).to_i
24
41
  @logger.warn "You have been rate limited. Retrying in #{seconds_left} seconds..." if @logger
25
42
 
26
43
  seconds_left.times do |i|
@@ -6,7 +6,7 @@ require 'zendesk_api/associations'
6
6
  require 'zendesk_api/verbs'
7
7
 
8
8
  module ZendeskAPI
9
- # Represents a resource that only holds data.
9
+ # Represents an abstract resource that only holds data.
10
10
  class Data
11
11
  include Associations
12
12
 
@@ -54,6 +54,7 @@ module ZendeskAPI
54
54
  # @param [Hash] attributes The optional attributes that describe the resource
55
55
  def initialize(client, attributes = {})
56
56
  raise "Expected a Hash for attributes, got #{attributes.inspect}" unless attributes.is_a?(Hash)
57
+
57
58
  @association = attributes.delete(:association) || Association.new(:class => self.class)
58
59
  @global_params = attributes.delete(:global) || {}
59
60
  @client = client
@@ -177,7 +178,7 @@ module ZendeskAPI
177
178
  include Destroy
178
179
  end
179
180
 
180
- # Represents a resource that can CRUD (create, read, update, delete).
181
+ # Represents an abstract resource that can CRUD (create, read, update, delete).
181
182
  class Resource < DataResource
182
183
  include Read
183
184
  include Create
@@ -5,7 +5,6 @@ module ZendeskAPI
5
5
  class User < Resource; end
6
6
  class UserRelated < DataResource; end
7
7
  class Category < Resource; end
8
- class OrganizationMembership < ReadResource; end
9
8
  class OrganizationSubscription < ReadResource; end
10
9
 
11
10
  # @internal Begin actual Resource definitions
@@ -126,6 +125,10 @@ module ZendeskAPI
126
125
 
127
126
  class OrganizationRelated < DataResource; end
128
127
 
128
+ class OrganizationMembership < ReadResource
129
+ extend CreateOrUpdate
130
+ end
131
+
129
132
  class Organization < Resource
130
133
  extend CreateMany
131
134
  extend CreateOrUpdate
@@ -274,44 +277,6 @@ module ZendeskAPI
274
277
  has Group
275
278
  end
276
279
 
277
- class Search
278
- class Result < Data; end
279
-
280
- # Creates a search collection
281
- def self.search(client, options = {})
282
- unless (%w{query external_id} & options.keys.map(&:to_s)).any?
283
- warn "you have not specified a query for this search"
284
- end
285
-
286
- ZendeskAPI::Collection.new(client, self, options)
287
- end
288
-
289
- # Quack like a Resource
290
- # Creates the correct resource class from the result_type passed in
291
- def self.new(client, attributes)
292
- result_type = attributes["result_type"]
293
-
294
- if result_type
295
- result_type = ZendeskAPI::Helpers.modulize_string(result_type)
296
- klass = ZendeskAPI.const_get(result_type) rescue nil
297
- end
298
-
299
- (klass || Result).new(client, attributes)
300
- end
301
-
302
- class << self
303
- def resource_name
304
- "search"
305
- end
306
-
307
- alias :resource_path :resource_name
308
-
309
- def model_key
310
- "results"
311
- end
312
- end
313
- end
314
-
315
280
  class Request < Resource
316
281
  class Comment < DataResource
317
282
  include Save
@@ -793,6 +758,11 @@ module ZendeskAPI
793
758
 
794
759
  class Target < Resource; end
795
760
 
761
+ class Invocation < Resource; end
762
+ class Webhook < Resource
763
+ has_many Invocation
764
+ end
765
+
796
766
  module Voice
797
767
  include DataNamespace
798
768
 
@@ -0,0 +1,51 @@
1
+ # `zendesk_api` gem root
2
+ module ZendeskAPI
3
+ # A rich factory that returns a class for your searches
4
+ class Search
5
+ # Creates a search collection
6
+ def self.search(client, options = {})
7
+ if (options.keys.map(&:to_s) & %w[query external_id]).empty?
8
+ warn "you have not specified a query for this search"
9
+ end
10
+
11
+ ZendeskAPI::Collection.new(client, self, options)
12
+ end
13
+
14
+ # Quack like a Resource
15
+ # Creates the correct resource class from `attributes[:result_type]`
16
+ def self.new(client, attributes)
17
+ present_result_type = (attributes[:result_type] || attributes["result_type"]).to_s
18
+ result_type = ZendeskAPI::Helpers.modulize_string(present_result_type)
19
+ klass = begin
20
+ ZendeskAPI.const_get(result_type)
21
+ rescue NameError
22
+ Result
23
+ end
24
+
25
+ (klass || Result).new(client, attributes)
26
+ end
27
+
28
+ class Result < Data; end
29
+
30
+ class << self
31
+ def resource_name
32
+ "search"
33
+ end
34
+ alias resource_path resource_name
35
+
36
+ def model_key
37
+ "results"
38
+ end
39
+ end
40
+ end
41
+
42
+ # This will use cursor pagination by default
43
+ class SearchExport < Search
44
+ class << self
45
+ def resource_name
46
+ "search/export"
47
+ end
48
+ alias resource_path resource_name
49
+ end
50
+ end
51
+ end
@@ -1,3 +1,3 @@
1
1
  module ZendeskAPI
2
- VERSION = "1.31.0"
2
+ VERSION = "1.35.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zendesk_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.31.0
4
+ version: 1.35.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Davidovitz
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-07-13 00:00:00.000000000 Z
12
+ date: 2022-01-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: faraday
@@ -40,7 +40,7 @@ dependencies:
40
40
  version: 3.5.2
41
41
  - - "<"
42
42
  - !ruby/object:Gem::Version
43
- version: 5.0.0
43
+ version: 6.0.0
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  version: 3.5.2
51
51
  - - "<"
52
52
  - !ruby/object:Gem::Version
53
- version: 5.0.0
53
+ version: 6.0.0
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: inflection
56
56
  requirement: !ruby/object:Gem::Requirement
@@ -130,6 +130,7 @@ files:
130
130
  - lib/zendesk_api/middleware/response/sanitize_response.rb
131
131
  - lib/zendesk_api/resource.rb
132
132
  - lib/zendesk_api/resources.rb
133
+ - lib/zendesk_api/search.rb
133
134
  - lib/zendesk_api/sideloading.rb
134
135
  - lib/zendesk_api/silent_mash.rb
135
136
  - lib/zendesk_api/track_changes.rb
@@ -143,9 +144,9 @@ licenses:
143
144
  - Apache-2.0
144
145
  metadata:
145
146
  bug_tracker_uri: https://github.com/zendesk/zendesk_api_client_rb/issues
146
- changelog_uri: https://github.com/zendesk/zendesk_api_client_rb/blob/v1.31.0/CHANGELOG.md
147
- documentation_uri: https://www.rubydoc.info/gems/zendesk_api/1.31.0
148
- source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/v1.31.0
147
+ changelog_uri: https://github.com/zendesk/zendesk_api_client_rb/blob/v1.35.0/CHANGELOG.md
148
+ documentation_uri: https://www.rubydoc.info/gems/zendesk_api/1.35.0
149
+ source_code_uri: https://github.com/zendesk/zendesk_api_client_rb/tree/v1.35.0
149
150
  wiki_uri: https://github.com/zendesk/zendesk_api_client_rb/wiki
150
151
  post_install_message:
151
152
  rdoc_options: []