zendesk_api 0.4.0.rc2 → 0.4.0.rc3

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