zendesk_api 0.1.7 → 0.1.8

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.
Files changed (42) hide show
  1. data/.yardopts +1 -1
  2. data/Gemfile.lock +3 -1
  3. data/Rakefile +1 -0
  4. data/Readme.md +38 -0
  5. data/lib/zendesk_api.rb +2 -3
  6. data/lib/zendesk_api/actions.rb +9 -2
  7. data/lib/zendesk_api/association.rb +28 -54
  8. data/lib/zendesk_api/client.rb +20 -5
  9. data/lib/zendesk_api/collection.rb +31 -16
  10. data/lib/zendesk_api/configuration.rb +1 -0
  11. data/lib/zendesk_api/helpers.rb +1 -0
  12. data/lib/zendesk_api/lru_cache.rb +1 -0
  13. data/lib/zendesk_api/middleware/request/etag_cache.rb +1 -0
  14. data/lib/zendesk_api/middleware/request/retry.rb +2 -0
  15. data/lib/zendesk_api/middleware/request/upload.rb +1 -0
  16. data/lib/zendesk_api/middleware/response/callback.rb +1 -0
  17. data/lib/zendesk_api/middleware/response/deflate.rb +1 -0
  18. data/lib/zendesk_api/middleware/response/gzip.rb +2 -0
  19. data/lib/zendesk_api/middleware/response/logger.rb +1 -0
  20. data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +1 -0
  21. data/lib/zendesk_api/rescue.rb +2 -0
  22. data/lib/zendesk_api/resource.rb +11 -6
  23. data/lib/zendesk_api/resources.rb +319 -0
  24. data/lib/zendesk_api/sideloading.rb +1 -0
  25. data/lib/zendesk_api/track_changes.rb +3 -2
  26. data/lib/zendesk_api/trackie.rb +1 -0
  27. data/lib/zendesk_api/version.rb +1 -1
  28. data/spec/association_spec.rb +1 -1
  29. data/spec/client_spec.rb +13 -2
  30. data/spec/collection_spec.rb +7 -7
  31. data/spec/data_resource_spec.rb +53 -66
  32. data/spec/read_resource_spec.rb +1 -1
  33. data/spec/resource_spec.rb +6 -6
  34. data/spec/spec_helper.rb +1 -1
  35. data/util/resource_handler.rb +68 -0
  36. data/util/verb_handler.rb +16 -0
  37. data/zendesk_api.gemspec +3 -2
  38. metadata +27 -12
  39. data/lib/zendesk_api/resources/forum.rb +0 -51
  40. data/lib/zendesk_api/resources/misc.rb +0 -79
  41. data/lib/zendesk_api/resources/ticket.rb +0 -97
  42. data/lib/zendesk_api/resources/user.rb +0 -59
@@ -1,4 +1,5 @@
1
1
  module ZendeskAPI
2
+ # Holds the configuration options for the client and connection
2
3
  class Configuration
3
4
  # @return [String] The basic auth username.
4
5
  attr_accessor :username
@@ -1,4 +1,5 @@
1
1
  module ZendeskAPI
2
+ # @private
2
3
  module Helpers
3
4
  # From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/modulize.rb
4
5
  def self.modulize_string(string)
@@ -1,5 +1,6 @@
1
1
  module ZendeskAPI
2
2
  # http://codesnippets.joyent.com/posts/show/12329
3
+ # @private
3
4
  class ZendeskAPI::LRUCache
4
5
  attr_accessor :size
5
6
 
@@ -5,6 +5,7 @@ module ZendeskAPI
5
5
  module Request
6
6
  # Request middleware that caches responses based on etags
7
7
  # can be removed once this is merged: https://github.com/pengwynn/faraday_middleware/pull/42
8
+ # @private
8
9
  class EtagCache < Faraday::Middleware
9
10
  def initialize(app, options = {})
10
11
  @app = app
@@ -2,8 +2,10 @@ require "faraday/middleware"
2
2
 
3
3
  module ZendeskAPI
4
4
  module Middleware
5
+ # @private
5
6
  module Request
6
7
  # Faraday middleware to handle HTTP Status 429 (rate limiting) / 503 (maintenance)
8
+ # @private
7
9
  class Retry < Faraday::Middleware
8
10
  DEFAULT_RETRY_AFTER = 10
9
11
  ERROR_CODES = [429, 503]
@@ -5,6 +5,7 @@ require 'tempfile'
5
5
  module ZendeskAPI
6
6
  module Middleware
7
7
  module Request
8
+ # @private
8
9
  class Upload < Faraday::Middleware
9
10
  def call(env)
10
11
  if env[:body]
@@ -3,6 +3,7 @@ require "faraday/response"
3
3
  module ZendeskAPI
4
4
  module Middleware
5
5
  module Response
6
+ # @private
6
7
  class Callback < Faraday::Response::Middleware
7
8
  def initialize(app, client)
8
9
  super(app)
@@ -4,6 +4,7 @@ module ZendeskAPI
4
4
  module Middleware
5
5
  module Response
6
6
  # Faraday middleware to handle content-encoding = inflate
7
+ # @private
7
8
  class Deflate < FaradayMiddleware::ResponseMiddleware
8
9
  define_parser do |body|
9
10
  Zlib::Inflate.inflate(body)
@@ -1,7 +1,9 @@
1
1
  require 'faraday_middleware/response_middleware'
2
2
 
3
3
  module ZendeskAPI
4
+ # @private
4
5
  module Middleware
6
+ # @private
5
7
  module Response
6
8
  # Faraday middleware to handle content-encoding = gzip
7
9
  class Gzip < FaradayMiddleware::ResponseMiddleware
@@ -4,6 +4,7 @@ module ZendeskAPI
4
4
  module Middleware
5
5
  module Response
6
6
  # Faraday middleware to handle logging
7
+ # @private
7
8
  class Logger < Faraday::Response::Middleware
8
9
  def initialize(app, logger = nil)
9
10
  super(app)
@@ -5,6 +5,7 @@ module ZendeskAPI
5
5
  module Middleware
6
6
  module Response
7
7
  # Parse ISO dates from response body
8
+ # @private
8
9
  class ParseIsoDates < Faraday::Response::Middleware
9
10
  def call(env)
10
11
  response = @app.call(env)
@@ -1,10 +1,12 @@
1
1
  module ZendeskAPI
2
+ # @private
2
3
  module Rescue
3
4
  def self.included(klass)
4
5
  klass.extend(Methods)
5
6
  klass.send(:include, Methods)
6
7
  end
7
8
 
9
+ # @private
8
10
  module Methods
9
11
  def log_error(e, method = false)
10
12
  if logger = (@client ? @client.config.logger : Kernel)
@@ -23,15 +23,12 @@ module ZendeskAPI
23
23
 
24
24
  alias :model_key :resource_name
25
25
 
26
- # Rails tries to load dependencies, which messes up automatic resource our own loading
27
- if method_defined?(:const_missing_without_dependencies)
28
- alias :const_missing :const_missing_without_dependencies
29
- end
30
-
26
+ # @private
31
27
  def only_send_unnested_params
32
28
  @unnested_params = true
33
29
  end
34
30
 
31
+ # @private
35
32
  def unnested_params
36
33
  @unnested_params ||= false
37
34
  end
@@ -50,7 +47,10 @@ module ZendeskAPI
50
47
  @association = attributes.delete(:association) || Association.new(:class => self.class)
51
48
  @client = client
52
49
  @attributes = ZendeskAPI::Trackie.new(attributes)
53
- ZendeskAPI::Client.check_deprecated_namespace_usage @attributes, self.class.singular_resource_name
50
+
51
+ if self.class.associations.none? {|a| a[:name] == self.class.singular_resource_name}
52
+ ZendeskAPI::Client.check_deprecated_namespace_usage @attributes, self.class.singular_resource_name
53
+ end
54
54
 
55
55
  @attributes.clear_changes unless new_record?
56
56
  end
@@ -72,6 +72,7 @@ module ZendeskAPI
72
72
  id.nil?
73
73
  end
74
74
 
75
+ # @private
75
76
  def loaded_associations
76
77
  self.class.associations.select do |association|
77
78
  loaded = @attributes.method_missing(association[:name])
@@ -84,15 +85,18 @@ module ZendeskAPI
84
85
  @association.generate_path(self, *args)
85
86
  end
86
87
 
88
+ # Passes #to_json to the underlying attributes hash
87
89
  def to_json(*args)
88
90
  method_missing(:to_json, *args)
89
91
  end
90
92
 
93
+ # @private
91
94
  def to_s
92
95
  "#{self.class.singular_resource_name}: #{attributes.inspect}"
93
96
  end
94
97
  alias :inspect :to_s
95
98
 
99
+ # Compares resources by class and id. If id is nil, then by object_id
96
100
  def ==(other)
97
101
  warn "Trying to compare #{other.class} to a Resource" if other && !other.is_a?(Data)
98
102
  other.is_a?(self.class) && ((other.id && other.id == id) || (other.object_id == self.object_id))
@@ -100,6 +104,7 @@ module ZendeskAPI
100
104
  alias :eql :==
101
105
  alias :hash :id
102
106
 
107
+ # @private
103
108
  def inspect
104
109
  "#<#{self.class.name} #{@attributes.to_hash.inspect}>"
105
110
  end
@@ -0,0 +1,319 @@
1
+ module ZendeskAPI
2
+ # @internal The following are redefined later, but needed by some circular resources (e.g. Ticket -> User, User -> Ticket)
3
+
4
+
5
+ class Ticket < Resource; end
6
+ class Forum < Resource; end
7
+ class User < Resource; end
8
+ class Category < Resource; end
9
+
10
+ # @internal Begin actual Resource definitions
11
+
12
+ class Locale < ReadResource; end
13
+ class CRMData < DataResource; end
14
+ class CRMDataStatus < DataResource; end
15
+ class CustomRole < DataResource; end
16
+ class Role < DataResource; end
17
+ class Topic < Resource; end
18
+ class Bookmark < Resource; end
19
+ class Ability < DataResource; end
20
+ class Macro < Resource; end
21
+ class Group < Resource; end
22
+ class Trigger < ReadResource; end
23
+ class SharingAgreement < ReadResource; end
24
+ class JobStatus < ReadResource; end
25
+
26
+ class Attachment < Data
27
+ def initialize(client, attributes)
28
+ if attributes.is_a?(Hash)
29
+ super
30
+ else
31
+ super(client, :file => attributes)
32
+ end
33
+ end
34
+
35
+ def save
36
+ upload = Upload.create!(@client, attributes)
37
+ self.token = upload.token
38
+ end
39
+
40
+ def to_param
41
+ token
42
+ end
43
+ end
44
+
45
+ class Upload < Data
46
+ include Create
47
+
48
+ only_send_unnested_params
49
+
50
+ has_many Attachment
51
+ end
52
+
53
+ class MobileDevice < Resource
54
+ # Clears this devices' badge
55
+ put :clear_badge
56
+ end
57
+
58
+ class Organization < Resource
59
+ has Ability, :inline => true
60
+ has Group
61
+
62
+ has_many Ticket
63
+ has_many User
64
+ end
65
+
66
+ class ForumSubscription < Resource
67
+ only_send_unnested_params
68
+ has Forum
69
+ has User
70
+ end
71
+
72
+ class Forum < Resource
73
+ has Category
74
+ has Organization
75
+ has Locale
76
+
77
+ has_many Topic
78
+ has_many :subscriptions, :class => ForumSubscription
79
+ end
80
+
81
+ class Category < Resource
82
+ has_many Forum
83
+ end
84
+
85
+ class TopicSubscription < Resource
86
+ only_send_unnested_params
87
+ has Topic
88
+ has User
89
+ end
90
+
91
+ class Topic < Resource
92
+ class TopicComment < Resource
93
+ has Topic
94
+ has User
95
+ has_many Attachment
96
+ end
97
+
98
+ class TopicVote < SingularResource
99
+ only_send_unnested_params
100
+ has Topic
101
+ has User
102
+ end
103
+
104
+ has Forum
105
+ has_many :comments, :class => TopicComment
106
+ has_many :subscriptions, :class => TopicSubscription
107
+ has :vote, :class => TopicVote
108
+
109
+ def votes(opts = {})
110
+ return @votes if @votes && !opts[:reload]
111
+
112
+ association = ZendeskAPI::Association.new(:class => TopicVote, :parent => self, :path => 'votes')
113
+ @votes = ZendeskAPI::Collection.new(@client, TopicVote, opts.merge(:association => association))
114
+ end
115
+ end
116
+
117
+ class Activity < Resource
118
+ has User
119
+ has :actor, :class => User
120
+ end
121
+
122
+ class Setting < DataResource
123
+ attr_reader :on
124
+
125
+ def initialize(client, attributes = {})
126
+ @on = attributes.first
127
+ super(client, attributes[1])
128
+ end
129
+ end
130
+
131
+ class SatisfactionRating < ReadResource
132
+ has :assignee, :class => User
133
+ has :requester, :class => User
134
+ has Ticket
135
+ has Group
136
+ end
137
+
138
+ class Search
139
+ class Result < Data; end
140
+
141
+ # Creates a search collection
142
+ def self.search(client, options = {})
143
+ unless (%w{query external_id} & options.keys.map(&:to_s)).any?
144
+ warn "you have not specified a query for this search"
145
+ end
146
+
147
+ ZendeskAPI::Collection.new(client, self, options)
148
+ end
149
+
150
+ # Creates the correct resource class from the result_type passed in
151
+ def self.new(client, attributes)
152
+ result_type = attributes["result_type"]
153
+
154
+ if result_type
155
+ result_type = ZendeskAPI::Helpers.modulize_string(result_type)
156
+ klass = ZendeskAPI.const_get(result_type) rescue nil
157
+ end
158
+
159
+ (klass || Result).new(client, attributes)
160
+ end
161
+
162
+ def self.resource_name
163
+ "search"
164
+ end
165
+
166
+ def self.model_key
167
+ "results"
168
+ end
169
+ end
170
+
171
+ class Request < Resource
172
+ class Comment < ReadResource
173
+ has_many Attachment, :inline => true
174
+ end
175
+
176
+ has_many Comment
177
+ has Organization
178
+ end
179
+
180
+ class TicketField < Resource; end
181
+
182
+ class TicketComment < Data
183
+ include Save
184
+
185
+ has_many :uploads, :class => Attachment, :inline => true
186
+ has :author, :class => User
187
+
188
+ def save
189
+ save_associations
190
+ true
191
+ end
192
+
193
+ alias :save! :save
194
+ end
195
+
196
+ class TicketMetric < ReadResource; end
197
+
198
+ class Ticket < Resource
199
+ class Audit < DataResource; end
200
+
201
+ has :requester, :class => User, :inline => :create
202
+ has :submitter, :class => User
203
+ has :assignee, :class => User
204
+ has_many :collaborators, :class => User
205
+ has_many Audit
206
+ has :metrics, :class => TicketMetric
207
+ has Group
208
+ has :forum_topic, :class => Topic
209
+ has Organization
210
+
211
+ has :comment, :class => TicketComment, :inline => true
212
+ has :last_comment, :class => TicketComment, :inline => true
213
+
214
+ # Gets a incremental export of tickets from the start_time until now.
215
+ # @param [Client] client The {Client} object to be used
216
+ # @param [Integer] start_time The start_time parameter
217
+ # @return [Collection] Collection of {Ticket}
218
+ def self.incremental_export(client, start_time)
219
+ ZendeskAPI::Collection.new(client, self, :path => "exports/tickets?start_time=#{start_time.to_i}")
220
+ end
221
+
222
+ # Imports a ticket through the imports/tickets endpoint
223
+ # @param [Client] client The {Client} object to be used
224
+ # @param [Hash] attributes The attributes to create.
225
+ # @return [Ticket] Created object or nil
226
+ def self.import(client, attributes)
227
+ ticket = new(client, attributes)
228
+ return unless ticket.save(:path => "imports/tickets")
229
+ ticket
230
+ end
231
+ end
232
+
233
+ class SuspendedTicket < ReadResource
234
+ include Destroy
235
+
236
+ # Recovers this suspended ticket to an actual ticket
237
+ put :recover
238
+ end
239
+
240
+ class ViewRow < DataResource
241
+ has Ticket
242
+
243
+ # @internal Optional columns
244
+
245
+ has Group
246
+ has :assignee, :class => User
247
+ has :requester, :class => User
248
+ has :submitter, :class => User
249
+ has Organization
250
+
251
+ def self.model_key
252
+ "rows"
253
+ end
254
+ end
255
+
256
+ class ViewExecution < Data
257
+ has_many :custom_fields, :class => TicketField
258
+ end
259
+
260
+ class View < ReadResource
261
+ has_many :rows, :class => ViewRow, :path => "execute"
262
+ has :execution, :class => ViewExecution
263
+
264
+ def self.preview(client, options = {})
265
+ Collection.new(client, ViewRow, options.merge(:path => "views/preview", :verb => :post))
266
+ end
267
+ end
268
+
269
+
270
+ class GroupMembership < Resource
271
+ has User
272
+ has Group
273
+ end
274
+
275
+ class User < Resource
276
+ class Identity < Resource
277
+ # Makes this identity the primary one bumping all other identities down one
278
+ put :make_primary
279
+
280
+ # Verifies this identity
281
+ put :verify
282
+
283
+ # Requests verification for this identity
284
+ put :request_verification
285
+ end
286
+
287
+ def initialize(*)
288
+ super
289
+
290
+ # Needed for side-loading to work
291
+ self.role_id = role.id if self.key?(:role)
292
+ end
293
+
294
+ has Organization
295
+
296
+ has CustomRole, :include => :roles
297
+ has Role, :inline => true, :include_key => :name
298
+ has Ability, :inline => true
299
+
300
+ has_many Identity
301
+
302
+ has_many Request
303
+ has_many :requested_tickets, :class => Ticket, :path => 'tickets/requested'
304
+ has_many :ccd_tickets, :class => Ticket, :path => 'tickets/ccd'
305
+
306
+ has_many Group
307
+ has_many GroupMembership
308
+ has_many Topic
309
+
310
+ has_many ForumSubscription
311
+ has_many TopicSubscription
312
+ has_many :topic_comments, :class => Topic::TopicComment
313
+ has_many :topic_votes, :class => Topic::TopicVote
314
+
315
+ has CRMData
316
+ has CRMDataStatus, :path => 'crm_data/status'
317
+ end
318
+ end
319
+