zendesk_api 0.4.0.rc2 → 0.4.0.rc3

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.
data/Gemfile.lock CHANGED
@@ -7,7 +7,7 @@ GIT
7
7
  PATH
8
8
  remote: .
9
9
  specs:
10
- zendesk_api (0.4.0.rc2)
10
+ zendesk_api (0.4.0.rc3)
11
11
  faraday (>= 0.8.0)
12
12
  faraday_middleware (>= 0.8.7)
13
13
  hashie (>= 1.2)
data/Readme.md CHANGED
@@ -86,7 +86,7 @@ One way to use the client is to pass it in as an argument to individual classes.
86
86
  ZendeskAPI::Ticket.new(client, :id => 1, :priority => "urgent") # doesn't actually send a request, must explicitly call #save
87
87
  ZendeskAPI::Ticket.create(client, :subject => "Test Ticket", :comment => { :value => "This is a test" }, :submitter_id => client.current_user.id, :priority => "urgent")
88
88
  ZendeskAPI::Ticket.find(client, :id => 1)
89
- ZendeskAPI::Ticket.delete(client, :id => 1)
89
+ ZendeskAPI::Ticket.destroy(client, :id => 1)
90
90
  ```
91
91
 
92
92
  Another way is to use the instance methods under client.
@@ -95,7 +95,7 @@ Another way is to use the instance methods under client.
95
95
  client.tickets.first
96
96
  client.tickets.find(:id => 1)
97
97
  client.tickets.create(:subject => "Test Ticket", :comment => { :value => "This is a test" }, :submitter_id => client.current_user.id, :priority => "urgent")
98
- client.tickets.delete(:id => 1)
98
+ client.tickets.destroy(:id => 1)
99
99
  ```
100
100
 
101
101
  The methods under ZendeskAPI::Client (such as .tickets) return an instance of ZendeskAPI::Collection a lazy-loaded list of that resource.
@@ -21,6 +21,8 @@ module ZendeskAPI
21
21
 
22
22
  @response = @client.connection.send(method, req_path) do |req|
23
23
  req.body = attributes_for_save.merge(@global_params)
24
+
25
+ yield req if block_given?
24
26
  end
25
27
 
26
28
  if @response.body && @response.body[self.class.singular_resource_name]
@@ -33,8 +35,8 @@ module ZendeskAPI
33
35
  end
34
36
 
35
37
  # Saves, returning false if it fails and attaching the errors
36
- def save(options={})
37
- save!(options)
38
+ def save(options = {}, &block)
39
+ save!(options, &block)
38
40
  rescue ZendeskAPI::Error::RecordInvalid => e
39
41
  @errors = e.errors
40
42
  false
@@ -58,7 +60,7 @@ module ZendeskAPI
58
60
  next unless send("#{association_name}_used?") && association = send(association_name)
59
61
 
60
62
  inline_creation = association_data[:inline] == :create && new_record?
61
- changed = association.is_a?(Collection) || !association.changes.empty?
63
+ changed = association.is_a?(Collection) || association.changed?
62
64
 
63
65
  if association.respond_to?(:save) && changed && !inline_creation && association.save
64
66
  self.send("#{association_name}=", association) # set id/ids columns
@@ -91,6 +93,8 @@ module ZendeskAPI
91
93
 
92
94
  response = client.connection.get(association.generate_path(options)) do |req|
93
95
  req.params = options
96
+
97
+ yield req if block_given?
94
98
  end
95
99
 
96
100
  new(client, response.body[singular_resource_name]).tap do |resource|
@@ -100,8 +104,8 @@ module ZendeskAPI
100
104
  end
101
105
 
102
106
  # Finds, returning nil if it fails
103
- def find(client, options = {})
104
- find!(client, options)
107
+ def find(client, options = {}, &block)
108
+ find!(client, options, &block)
105
109
  rescue ZendeskAPI::Error::ClientError => e
106
110
  nil
107
111
  end
@@ -118,13 +122,16 @@ module ZendeskAPI
118
122
  # Create a resource given the attributes passed in.
119
123
  # @param [Client] client The {Client} object to be used
120
124
  # @param [Hash] attributes The attributes to create.
121
- def create!(client, attributes = {})
125
+ def create!(client, attributes = {}, &block)
122
126
  ZendeskAPI::Client.check_deprecated_namespace_usage attributes, singular_resource_name
123
- new(client, attributes).tap(&:save!)
127
+
128
+ new(client, attributes).tap do |resource|
129
+ resource.save!(&block)
130
+ end
124
131
  end
125
132
 
126
- def create(client, attributes = {})
127
- create!(client, attributes)
133
+ def create(client, attributes = {}, &block)
134
+ create!(client, attributes, &block)
128
135
  rescue ZendeskAPI::Error::ClientError
129
136
  nil
130
137
  end
@@ -145,12 +152,16 @@ module ZendeskAPI
145
152
  # @return [Boolean] Successful?
146
153
  def destroy!
147
154
  return false if destroyed? || new_record?
148
- @client.connection.delete(url || path)
155
+
156
+ @client.connection.delete(url || path) do |req|
157
+ yield req if block_given?
158
+ end
159
+
149
160
  @destroyed = true
150
161
  end
151
162
 
152
- def destroy
153
- destroy!
163
+ def destroy(&block)
164
+ destroy!(&block)
154
165
  rescue ZendeskAPI::Error::ClientError
155
166
  false
156
167
  end
@@ -159,19 +170,14 @@ module ZendeskAPI
159
170
  # Deletes a resource given the id passed in.
160
171
  # @param [Client] client The {Client} object to be used
161
172
  # @param [Hash] opts The optional parameters to pass. Defaults to {}
162
- def destroy!(client, opts = {})
163
- @client = client # so we can use client.logger in rescue
164
- association = opts.delete(:association) || Association.new(:class => self)
165
-
166
- client.connection.delete(association.generate_path(opts)) do |req|
167
- req.params = opts
168
- end
173
+ def destroy!(client, opts = {}, &block)
174
+ new(client, opts).destroy!(&block)
169
175
 
170
176
  true
171
177
  end
172
178
 
173
- def destroy(client, attributes = {})
174
- destroy!(client, attributes)
179
+ def destroy(client, attributes = {}, &block)
180
+ destroy!(client, attributes, &block)
175
181
  rescue ZendeskAPI::Error::ClientError
176
182
  false
177
183
  end
@@ -189,17 +195,17 @@ module ZendeskAPI
189
195
  # Updates a resource given the id passed in.
190
196
  # @param [Client] client The {Client} object to be used
191
197
  # @param [Hash] attributes The attributes to update. Default to {}
192
- def update(client, attributes = {})
193
- update!(client, attributes)
198
+ def update(client, attributes = {}, &block)
199
+ update!(client, attributes, &block)
194
200
  rescue ZendeskAPI::Error::ClientError
195
201
  false
196
202
  end
197
203
 
198
- def update!(client, attributes = {})
204
+ def update!(client, attributes = {}, &block)
199
205
  ZendeskAPI::Client.check_deprecated_namespace_usage attributes, singular_resource_name
200
- resource = new(client, { :id => attributes.delete(:id), :global => attributes.delete(:global) })
206
+ resource = new(client, :id => attributes.delete(:id), :global => attributes.delete(:global), :association => attributes.delete(:association))
201
207
  resource.attributes.merge!(attributes)
202
- resource.save!(:force_update => resource.is_a?(SingularResource))
208
+ resource.save!(:force_update => resource.is_a?(SingularResource), &block)
203
209
  resource
204
210
  end
205
211
  end
@@ -59,7 +59,8 @@ module ZendeskAPI
59
59
  :path => options.delete(:path),
60
60
  :include => (options.delete(:include) || klass.resource_name).to_s,
61
61
  :include_key => (options.delete(:include_key) || :id).to_s,
62
- :singular => options.delete(:singular)
62
+ :singular => options.delete(:singular),
63
+ :extensions => Array(options.delete(:extend))
63
64
  }
64
65
  end
65
66
 
@@ -171,15 +172,23 @@ module ZendeskAPI
171
172
  klass.find(@client, :id => id, :association => instance_association)
172
173
  end.compact
173
174
  elsif (resources = method_missing(association[:name].to_sym)) && resources.any?
174
- resources.map do |res|
175
- klass.new(@client, res.merge(:association => instance_association))
176
- end
175
+ resources.map {|res| wrap_resource(res, association)}
177
176
  else
178
- ZendeskAPI::Collection.new(@client, klass, instance_opts.merge(:association => instance_association))
177
+ []
179
178
  end
180
179
 
181
- send("#{association[:id_column]}=", resources.map(&:id)) if resource && has_key?(association[:id_column])
182
- instance_variable_set("@#{association[:name]}", resources)
180
+ collection = ZendeskAPI::Collection.new(@client, klass, instance_opts.merge(:association => instance_association))
181
+
182
+ if association[:extensions].any?
183
+ collection.extend(*association[:extensions])
184
+ end
185
+
186
+ if resources.any?
187
+ collection.replace(resources)
188
+ end
189
+
190
+ send("#{association[:id_column]}=", resources.map(&:id)) if has_key?(association[:id_column])
191
+ instance_variable_set("@#{association[:name]}", collection)
183
192
  end
184
193
  end
185
194
 
@@ -126,8 +126,7 @@ module ZendeskAPI
126
126
  raise "this collection is for #{@resource_class}"
127
127
  end
128
128
  else
129
- item.merge!(:association => @association) if item.is_a?(Hash)
130
- @resources << @resource_class.new(@client, item)
129
+ @resources << wrap_resource(item)
131
130
  end
132
131
  end
133
132
 
@@ -142,7 +141,7 @@ module ZendeskAPI
142
141
  if @resources && (!@fetchable || !reload)
143
142
  return @resources
144
143
  elsif association && association.options.parent && association.options.parent.new_record?
145
- return @resources = []
144
+ return (@resources = [])
146
145
  end
147
146
 
148
147
  @response = get_response(@query || self.path)
@@ -299,17 +298,19 @@ module ZendeskAPI
299
298
  end
300
299
 
301
300
  def _save(method = :save)
302
- if @resources
303
- @resources.map! do |item|
304
- if item.respond_to?(method) && !item.changes.empty?
305
- item.send(method)
306
- end
301
+ return self unless @resources
302
+
303
+ result = true
307
304
 
308
- item
305
+ @resources.map! do |item|
306
+ if item.respond_to?(method) && item.changed?
307
+ result &&= item.send(method)
309
308
  end
309
+
310
+ item
310
311
  end
311
312
 
312
- self
313
+ result
313
314
  end
314
315
 
315
316
  ## Initialize
@@ -351,12 +352,27 @@ module ZendeskAPI
351
352
 
352
353
  def handle_response(body)
353
354
  results = body.delete(@resource_class.model_key) || body.delete("results")
354
- @resources = results.map {|res| @resource_class.new(@client, res)}
355
+
356
+ @resources = results.map do |res|
357
+ wrap_resource(res)
358
+ end
355
359
 
356
360
  set_page_and_count(body)
357
361
  set_includes(@resources, @includes, body)
358
362
  end
359
363
 
364
+ # Simplified Associations#wrap_resource
365
+ def wrap_resource(res)
366
+ case res
367
+ when Array
368
+ wrap_resource(Hash[*res])
369
+ when Hash
370
+ @resource_class.new(@client, res.merge(:association => association))
371
+ else
372
+ @resource_class.new(@client, :id => res, :association => association)
373
+ end
374
+ end
375
+
360
376
  ## Method missing
361
377
 
362
378
  def array_method(name, *args, &block)
@@ -20,13 +20,55 @@ module ZendeskAPI
20
20
  class SharingAgreement < ReadResource; end
21
21
  class JobStatus < ReadResource; end
22
22
 
23
+ class Tag < DataResource
24
+ include Update
25
+ include Destroy
26
+
27
+ alias :name :id
28
+
29
+ def path(opts = {})
30
+ raise "tags must have parent resource" unless association.options.parent
31
+ super(opts.merge(:with_parent => true, :with_id => false))
32
+ end
33
+
34
+ def changed?
35
+ true
36
+ end
37
+
38
+ def destroy!
39
+ super do |req|
40
+ req.body = attributes_for_save
41
+ end
42
+ end
43
+
44
+ module Update
45
+ def _save(method = :save)
46
+ return self unless @resources
47
+
48
+ client.connection.post(path) do |req|
49
+ req.body = { :tags => @resources.map(&:id) }
50
+ end
51
+
52
+ true
53
+ rescue Faraday::Error::ClientError => e
54
+ if method == :save
55
+ false
56
+ else
57
+ raise e
58
+ end
59
+ end
60
+ end
61
+
62
+ def attributes_for_save
63
+ { self.class.resource_name => [id] }
64
+ end
65
+ end
66
+
23
67
  class Attachment < Data
24
68
  def initialize(client, attributes)
25
- if attributes.is_a?(Hash)
26
- super
27
- else
28
- super(client, :file => attributes)
29
- end
69
+ attributes[:file] ||= attributes.delete(:id)
70
+
71
+ super
30
72
  end
31
73
 
32
74
  def save
@@ -65,6 +107,7 @@ module ZendeskAPI
65
107
 
66
108
  has_many Ticket
67
109
  has_many User
110
+ has_many Tag, :extend => Tag::Update
68
111
  end
69
112
 
70
113
  class ForumSubscription < Resource
@@ -120,6 +163,7 @@ module ZendeskAPI
120
163
  has_many :comments, :class => TopicComment
121
164
  has_many :subscriptions, :class => TopicSubscription
122
165
  has :vote, :class => TopicVote
166
+ has_many Tag, :extend => Tag::Update
123
167
 
124
168
  def votes(opts = {})
125
169
  return @votes if @votes && !opts[:reload]
@@ -138,8 +182,13 @@ module ZendeskAPI
138
182
  attr_reader :on
139
183
 
140
184
  def initialize(client, attributes = {})
141
- @on = attributes.first
142
- super(client, attributes[1])
185
+ # Try and find the root key
186
+ @on = (attributes.keys.map(&:to_s) - %w{association options}).first
187
+
188
+ # Make what's inside that key the root attributes
189
+ attributes.merge!(attributes.delete(@on))
190
+
191
+ super
143
192
  end
144
193
  end
145
194
 
@@ -212,8 +261,6 @@ module ZendeskAPI
212
261
  has :author, :class => User
213
262
  end
214
263
 
215
- class Tag < Resource; end
216
-
217
264
  class Comment < Data
218
265
  include Save
219
266
 
@@ -242,6 +289,8 @@ module ZendeskAPI
242
289
  has :last_comment, :class => Comment, :inline => true
243
290
  has_many :last_comments, :class => Comment, :inline => true
244
291
 
292
+ has_many Tag, :extend => Tag::Update
293
+
245
294
  # Gets a incremental export of tickets from the start_time until now.
246
295
  # @param [Client] client The {Client} object to be used
247
296
  # @param [Integer] start_time The start_time parameter
@@ -399,12 +448,20 @@ module ZendeskAPI
399
448
  class UserField < Resource; end
400
449
  class OrganizationField < Resource; end
401
450
 
402
- class OAuthClient < Resource
451
+ class OauthClient < Resource
403
452
  namespace "oauth"
453
+
454
+ def self.singular_resource_name
455
+ "client"
456
+ end
404
457
  end
405
458
 
406
- class OAuthToken < ReadResource
459
+ class OauthToken < ReadResource
407
460
  include Destroy
408
461
  namespace "oauth"
462
+
463
+ def self.singular_resource_name
464
+ "token"
465
+ end
409
466
  end
410
467
  end
@@ -14,7 +14,7 @@ module ZendeskAPI
14
14
  end
15
15
  end
16
16
 
17
- resources = [resource_or_resources].flatten.compact
17
+ resources = to_array(resource_or_resources)
18
18
  resource_class = resources.first.class
19
19
 
20
20
  return if resources.empty?
@@ -43,9 +43,17 @@ module ZendeskAPI
43
43
  loaded_associations.each do |association|
44
44
  loaded = resource.send(association[:name])
45
45
  next unless loaded
46
- _side_load(name, association[:class], [loaded].flatten)
46
+ _side_load(name, association[:class], to_array(loaded))
47
47
  end
48
48
  end
49
49
  end
50
+
51
+ def to_array(item)
52
+ if item.is_a?(Collection)
53
+ item
54
+ else
55
+ [item].flatten.compact
56
+ end
57
+ end
50
58
  end
51
59
  end
@@ -1,3 +1,3 @@
1
1
  module ZendeskAPI
2
- VERSION = "0.4.0.rc2"
2
+ VERSION = "0.4.0.rc3"
3
3
  end
@@ -73,27 +73,32 @@ describe ZendeskAPI::Association do
73
73
  it "should cache a set object" do
74
74
  instance.children = [child]
75
75
  instance.children.map(&:id).should == [1]
76
+ instance.children.should be_instance_of(ZendeskAPI::Collection)
76
77
  end
77
78
 
78
79
  it "should set ids" do
79
80
  instance.children_ids = []
80
81
  instance.children = [child]
81
82
  instance.children_ids.should == [child.id]
83
+ instance.children.should be_instance_of(ZendeskAPI::Collection)
82
84
  end
83
85
 
84
86
  it "should build and cache objects set via hash" do
85
87
  instance.children = [{:id => 2}]
86
88
  instance.children.map(&:id).should == [2]
89
+ instance.children.should be_instance_of(ZendeskAPI::Collection)
87
90
  end
88
91
 
89
92
  it "should build a object set via id" do
90
93
  instance.children = [2]
91
94
  instance.children.map(&:id).should == [2]
95
+ instance.children.should be_instance_of(ZendeskAPI::Collection)
92
96
  end
93
97
 
94
98
  it "should fetch unknown objects" do
95
99
  stub_json_request(:get, %r{test_resources/1/children}, json(:test_children => [{:id => 2}, {:id => 3}]))
96
100
  instance.children.map(&:id).should == [2,3]
101
+ instance.children.should be_instance_of(ZendeskAPI::Collection)
97
102
  end
98
103
 
99
104
  it "is not used when not used" do
@@ -357,7 +357,7 @@ describe ZendeskAPI::Collection do
357
357
  end
358
358
 
359
359
  context "with a hash" do
360
- let(:object) { mock('ZendeskAPI::TestResource', :changes => [:xxx]) }
360
+ let(:object) { mock('ZendeskAPI::TestResource', :changes => [:xxx], :changed? => true) }
361
361
 
362
362
  it "should call create with those options" do
363
363
  ZendeskAPI::TestResource.should_receive(:new).
@@ -391,8 +391,11 @@ describe ZendeskAPI::Collection do
391
391
 
392
392
  context "with everything else" do
393
393
  it "should pass to new, since this is how attachment handles it" do
394
- attachment = mock(:changes => [:xxx])
395
- ZendeskAPI::TestResource.should_receive(:new).with(client, "img.jpg").and_return attachment
394
+ attachment = mock(:changes => [:xxx], :changed? => true)
395
+ ZendeskAPI::TestResource.should_receive(:new).
396
+ with(client, :id => "img.jpg", :association => instance_of(ZendeskAPI::Association)).
397
+ and_return attachment
398
+
396
399
  subject << "img.jpg"
397
400
 
398
401
  attachment.should_receive :save
@@ -44,7 +44,7 @@ def client
44
44
  config.retry = true
45
45
  end
46
46
 
47
- client.config.logger.level = (ENV["LOG"] ? Logger::INFO : Logger::WARN)
47
+ client.config.logger.level = (ENV["LOG"] ? Logger::DEBUG : Logger::WARN)
48
48
  client.config.cache.size = 0
49
49
 
50
50
  client
@@ -0,0 +1,53 @@
1
+ require 'core/spec_helper'
2
+
3
+ describe ZendeskAPI::Tag, :vcr, :not_findable do
4
+ it_should_be_readable :tags
5
+
6
+ [organization, topic, ticket].each do |object|
7
+ under object do
8
+ before(:each) do
9
+ parent.tags = %w{tag2 tag3}
10
+ parent.tags.save!
11
+ end
12
+
13
+ it "can be set" do
14
+ tags.should == %w{tag2 tag3}
15
+ end
16
+
17
+ it "should be removable" do
18
+ parent.tags.destroy!(:id => "tag2")
19
+
20
+ tags.should == %w{tag3}
21
+ end
22
+
23
+ it "should be updatable" do
24
+ parent.tags.update!(:id => "tag4")
25
+
26
+ tags.should == %w{tag2 tag3 tag4}
27
+ end
28
+
29
+ it "should be savable" do
30
+ parent.tags << "tag4"
31
+ parent.tags.save!
32
+
33
+ tags.should == %w{tag2 tag3 tag4}
34
+ end
35
+
36
+ it "should be modifiable" do
37
+ parent.tags.delete(ZendeskAPI::Tag.new(nil, :id => "tag2"))
38
+ parent.tags.save!
39
+
40
+ tags.should == %w{tag3}
41
+
42
+ parent.tags.delete_if {|tag| tag.id == "tag3"}
43
+ parent.tags.save!
44
+
45
+ tags.should be_empty
46
+ end
47
+ end
48
+ end
49
+
50
+ def tags
51
+ parent.tags.fetch!(:reload).map(&:id).sort
52
+ end
53
+ end
@@ -5,6 +5,8 @@ module ResourceMacros
5
5
 
6
6
  def under(object, &blk)
7
7
  context "under a #{object.class.singular_resource_name}" do
8
+ let(:parent) { object }
9
+
8
10
  define_method(:default_options) do
9
11
  { "#{object.class.singular_resource_name}_id" => object.id }
10
12
  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: 0.4.0.rc2
4
+ version: 0.4.0.rc3
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-06-20 00:00:00.000000000 Z
13
+ date: 2013-07-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bump
@@ -490,6 +490,7 @@ files:
490
490
  - spec/live/satisfaction_rating_spec.rb
491
491
  - spec/live/setting_spec.rb
492
492
  - spec/live/suspended_ticket_spec.rb
493
+ - spec/live/tag_spec.rb
493
494
  - spec/live/ticket_field_spec.rb
494
495
  - spec/live/ticket_metrics_spec.rb
495
496
  - spec/live/ticket_spec.rb
@@ -585,6 +586,7 @@ test_files:
585
586
  - spec/live/satisfaction_rating_spec.rb
586
587
  - spec/live/setting_spec.rb
587
588
  - spec/live/suspended_ticket_spec.rb
589
+ - spec/live/tag_spec.rb
588
590
  - spec/live/ticket_field_spec.rb
589
591
  - spec/live/ticket_metrics_spec.rb
590
592
  - spec/live/ticket_spec.rb