zendesk2 0.0.13 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +30 -25
- data/lib/zendesk2/attributes.rb +23 -0
- data/lib/zendesk2/client/models/categories.rb +12 -0
- data/lib/zendesk2/client/models/category.rb +38 -0
- data/lib/zendesk2/client/models/forum.rb +50 -0
- data/lib/zendesk2/client/models/forums.rb +12 -0
- data/lib/zendesk2/client/models/organization.rb +3 -1
- data/lib/zendesk2/client/models/organizations.rb +2 -12
- data/lib/zendesk2/client/models/ticket.rb +9 -13
- data/lib/zendesk2/client/models/tickets.rb +2 -8
- data/lib/zendesk2/client/models/user.rb +7 -9
- data/lib/zendesk2/client/models/users.rb +2 -8
- data/lib/zendesk2/client/requests/create_category.rb +32 -0
- data/lib/zendesk2/client/requests/create_forum.rb +33 -0
- data/lib/zendesk2/client/requests/create_user.rb +25 -6
- data/lib/zendesk2/client/requests/destroy_category.rb +27 -0
- data/lib/zendesk2/client/requests/destroy_forum.rb +28 -0
- data/lib/zendesk2/client/requests/get_categories.rb +18 -0
- data/lib/zendesk2/client/requests/get_category.rb +32 -0
- data/lib/zendesk2/client/requests/get_forum.rb +26 -0
- data/lib/zendesk2/client/requests/get_forums.rb +18 -0
- data/lib/zendesk2/client/requests/search.rb +2 -2
- data/lib/zendesk2/client/requests/update_category.rb +29 -0
- data/lib/zendesk2/client/requests/update_forum.rb +30 -0
- data/lib/zendesk2/client/requests/update_user.rb +26 -9
- data/lib/zendesk2/client.rb +24 -3
- data/lib/zendesk2/searchable.rb +17 -0
- data/lib/zendesk2/version.rb +1 -1
- data/lib/zendesk2.rb +3 -0
- data/spec/categories_spec.rb +9 -0
- data/spec/forums_spec.rb +9 -0
- data/spec/shared/resource.rb +8 -1
- data/spec/users_spec.rb +15 -1
- data/zendesk2.gemspec +1 -1
- metadata +23 -3
data/README.md
CHANGED
@@ -20,47 +20,52 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
Default credentials will be read in from `~/.zendesk2` file in YAML format.
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
```yaml
|
24
|
+
---
|
25
|
+
:subdomain: zendeskdev
|
26
|
+
:username: zendeskedge@example.com
|
27
|
+
:password: wickedsecurepassword
|
28
|
+
```
|
27
29
|
|
28
30
|
### Creating the client
|
29
31
|
|
30
32
|
Either the absolute url or the subdomain is required. Username and password is always required.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
```ruby
|
34
|
+
Zendesk2::Client.new(subdomain: "engineyard", username: "orchestra", password: "gwoo")
|
35
|
+
=> #<Zendesk2::Client::Real:0x007f99da1f9430 @url="https://engineyard.zendesk.com/api/v2", @username="orchestra", @password="gwoo", …>
|
36
|
+
```
|
35
37
|
or
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
```ruby
|
39
|
+
Zendesk2::Client.new(url: "http://support.cloud.engineyard.com", username: "mate", password: "bambilla")
|
40
|
+
=> #<Zendesk2::Client::Real:0x007fd1bae486b0 @url="http://support.cloud.engineyard.com", @username="mate", @password="bambilla", …>
|
41
|
+
```
|
39
42
|
### Resources
|
40
43
|
|
41
44
|
#### Collections
|
42
45
|
|
43
46
|
Currently support resources
|
44
47
|
|
48
|
+
* Categories
|
45
49
|
* User
|
46
50
|
* Ticket
|
47
51
|
* Organization
|
52
|
+
* Forums
|
48
53
|
|
49
54
|
All collection are accessed like so:
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
55
|
+
```ruby
|
56
|
+
client.users.all
|
57
|
+
=> <Zendesk2::Client::Users
|
58
|
+
count=1779,
|
59
|
+
next_page_link="https://dev.zendesk.com/api/v2/users.json?page=2",
|
60
|
+
previous_page_link=nil
|
61
|
+
[
|
62
|
+
<Zendesk2::Client::User
|
63
|
+
id=125394183,
|
64
|
+
url="https://dev.zendesk.com/api/v2/users/125394183.json",
|
65
|
+
...
|
66
|
+
>
|
67
|
+
]
|
68
|
+
```
|
64
69
|
Collections also respond to `create` and `new`
|
65
70
|
|
66
71
|
client.users.create(email: "ohhai@example.org", name: "lulz")
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Zendesk2::Attributes
|
2
|
+
def assoc_reader(name, options={})
|
3
|
+
assoc_key = options[:key] || "#{name}_id"
|
4
|
+
collection = options[:collection] || "#{name}s"
|
5
|
+
define_method(name) do
|
6
|
+
self.connection.send(collection).get(self.send(assoc_key))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def assoc_writer(name, options={})
|
11
|
+
assoc_key = options[:key] || "#{name}_id"
|
12
|
+
define_method("#{name}=") do |assoc|
|
13
|
+
self.send("#{assoc_key}=", assoc.id)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def assoc_accessor(name, options={})
|
18
|
+
assoc_reader(name, options)
|
19
|
+
assoc_writer(name, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: collection
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Zendesk2::Client::Categories < Cistern::Collection
|
2
|
+
include Zendesk2::PagedCollection
|
3
|
+
include Zendesk2::Searchable
|
4
|
+
|
5
|
+
model Zendesk2::Client::Category
|
6
|
+
|
7
|
+
self.collection_method= :get_categories
|
8
|
+
self.collection_root= "categories"
|
9
|
+
self.model_method= :get_category
|
10
|
+
self.model_root= "category"
|
11
|
+
self.search_type= "category"
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Zendesk2::Client::Category < Cistern::Model
|
2
|
+
PARAMS = %w[id name description position]
|
3
|
+
|
4
|
+
identity :id, type: :integer # ro[yes] mandatory[no] Automatically assigned during creation
|
5
|
+
attribute :url, type: :string # ro[yes] mandatory[no] The API url of this category
|
6
|
+
attribute :name, type: :string # ro[no] mandatory[yes] The name of the category
|
7
|
+
attribute :description, type: :string # ro[no] mandatory[no] The description of the category
|
8
|
+
attribute :position, type: :integer # ro[no] mandatory[no] The position of this category relative to other categories
|
9
|
+
attribute :created_at, type: :date # ro[yes] mandatory[no] The time the category was created
|
10
|
+
attribute :updated_at, type: :date # ro[yes] mandatory[no] The time of the last update of the category
|
11
|
+
|
12
|
+
def destroy
|
13
|
+
requires :id
|
14
|
+
|
15
|
+
connection.destroy_category("id" => self.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def destroyed?
|
19
|
+
!self.reload
|
20
|
+
end
|
21
|
+
|
22
|
+
def save
|
23
|
+
data = if new_record?
|
24
|
+
requires :name
|
25
|
+
connection.create_category(params).body["category"]
|
26
|
+
else
|
27
|
+
requires :id
|
28
|
+
connection.update_category(params).body["category"]
|
29
|
+
end
|
30
|
+
merge_attributes(data)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def params
|
36
|
+
Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), *PARAMS)
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Zendesk2::Client::Forum < Cistern::Model
|
2
|
+
extend Zendesk2::Attributes
|
3
|
+
|
4
|
+
PARAMS = %w[id name description category_id organization_id locale_id locked position forum_type access]
|
5
|
+
|
6
|
+
identity :id, type: :integer # ro yes mandatory no Automatically assigned upon creation
|
7
|
+
attribute :url, type: :string # ro yes mandatory no The API url of this forum
|
8
|
+
attribute :name, type: :string # ro no mandatory yes The name of the forum
|
9
|
+
attribute :description, type: :string # ro no mandatory no A description of the forum
|
10
|
+
attribute :category_id, type: :integer # ro no mandatory no Category this forum is in
|
11
|
+
attribute :organization_id, type: :integer # ro no mandatory no Organization this forum is restricted to
|
12
|
+
attribute :locale_id, type: :integer # ro no mandatory no User locale id this forum is restricted to
|
13
|
+
attribute :locked, type: :boolean # ro no mandatory no Whether this forum is locked such that new entries and comments cannot be made
|
14
|
+
attribute :unanswered_topics, type: :integer # ro yes mandatory no Contains the number of unanswered questions if this forum's topics are questions.
|
15
|
+
attribute :position, type: :integer # ro no mandatory no The position of this forum relative to other forums in the same category
|
16
|
+
attribute :forum_type, type: :string # ro no mandatory no The type of the topics in this forum, valid values: "articles", "ideas" or "questions"
|
17
|
+
attribute :access, type: :string # ro no mandatory no Who has access to this forum, valid values: "everybody", "logged-in users" or "agents only"
|
18
|
+
attribute :created_at, type: :date # ro yes mandatory no The time the forum was created
|
19
|
+
attribute :updated_at, type: :date # ro yes mandatory no The time of the last update of the forum
|
20
|
+
|
21
|
+
assoc_accessor :organization
|
22
|
+
assoc_accessor :category
|
23
|
+
|
24
|
+
def destroy
|
25
|
+
requires :identity
|
26
|
+
|
27
|
+
connection.destroy_forum("id" => self.identity)
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroyed?
|
31
|
+
!self.reload
|
32
|
+
end
|
33
|
+
|
34
|
+
def save
|
35
|
+
data = if new_record?
|
36
|
+
requires :name
|
37
|
+
connection.create_forum(params).body["forum"]
|
38
|
+
else
|
39
|
+
requires :identity
|
40
|
+
connection.update_forum(params).body["forum"]
|
41
|
+
end
|
42
|
+
merge_attributes(data)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def params
|
48
|
+
Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), *PARAMS)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Zendesk2::Client::Forums < Cistern::Collection
|
2
|
+
include Zendesk2::PagedCollection
|
3
|
+
include Zendesk2::Searchable
|
4
|
+
|
5
|
+
model Zendesk2::Client::Forum
|
6
|
+
|
7
|
+
self.collection_method= :get_forums
|
8
|
+
self.collection_root= "forums"
|
9
|
+
self.model_method= :get_forum
|
10
|
+
self.model_root= "forum"
|
11
|
+
self.search_type= "forum"
|
12
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
class Zendesk2::Client::Organization < Cistern::Model
|
2
|
+
PARAMS = %w[id details domain_names external_id group_id shared_comments shared_tickets tags name notes]
|
2
3
|
identity :id, type: :integer
|
4
|
+
attribute :url, type: :string
|
3
5
|
attribute :created_at, type: :time
|
4
6
|
attribute :details, type: :string
|
5
7
|
attribute :domain_names, type: :array
|
@@ -56,7 +58,7 @@ class Zendesk2::Client::Organization < Cistern::Model
|
|
56
58
|
private
|
57
59
|
|
58
60
|
def params
|
59
|
-
writable_attributes = Cistern::Hash.slice(Zendesk2.stringify_keys(attributes),
|
61
|
+
writable_attributes = Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), *PARAMS)
|
60
62
|
writable_attributes.delete("external_id") if writable_attributes["external_id"].to_s == "0"
|
61
63
|
writable_attributes.delete("group_id") if writable_attributes["group_id"].to_s == "0"
|
62
64
|
writable_attributes
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class Zendesk2::Client::Organizations < Cistern::Collection
|
2
2
|
include Zendesk2::PagedCollection
|
3
|
+
include Zendesk2::Searchable
|
3
4
|
|
4
5
|
model Zendesk2::Client::Organization
|
5
6
|
|
@@ -7,16 +8,5 @@ class Zendesk2::Client::Organizations < Cistern::Collection
|
|
7
8
|
self.collection_root= "organizations"
|
8
9
|
self.model_method= :get_organization
|
9
10
|
self.model_root= "organization"
|
10
|
-
|
11
|
-
def current
|
12
|
-
new(connection.get_current_organization.body["organization"])
|
13
|
-
end
|
14
|
-
|
15
|
-
def search(parameters)
|
16
|
-
body = connection.search(parameters.merge("type" => "organization")).body
|
17
|
-
if data = body.delete("results")
|
18
|
-
load(data)
|
19
|
-
end
|
20
|
-
merge_attributes(body)
|
21
|
-
end
|
11
|
+
self.search_type= "organization"
|
22
12
|
end
|
@@ -1,4 +1,8 @@
|
|
1
1
|
class Zendesk2::Client::Ticket < Cistern::Model
|
2
|
+
extend Zendesk2::Attributes
|
3
|
+
|
4
|
+
PARAMS = %w[external_id via requester_id submitter_id assignee_id organization_id subject description fields recipient status collaborator_ids]
|
5
|
+
|
2
6
|
identity :id, type: :id
|
3
7
|
attribute :external_id
|
4
8
|
attribute :via
|
@@ -23,6 +27,10 @@ class Zendesk2::Client::Ticket < Cistern::Model
|
|
23
27
|
attribute :tags, type: :array
|
24
28
|
attribute :fields, type: :array
|
25
29
|
|
30
|
+
assoc_reader :organization
|
31
|
+
assoc_accessor :requester
|
32
|
+
assoc_reader :submitter
|
33
|
+
|
26
34
|
def save
|
27
35
|
if new_record?
|
28
36
|
requires :subject, :description
|
@@ -53,22 +61,10 @@ class Zendesk2::Client::Ticket < Cistern::Model
|
|
53
61
|
!self.reload
|
54
62
|
end
|
55
63
|
|
56
|
-
def requester=(requester)
|
57
|
-
self.requester_id= requester.id
|
58
|
-
end
|
59
|
-
|
60
|
-
def requester
|
61
|
-
self.connection.users.get(self.requester_id)
|
62
|
-
end
|
63
|
-
|
64
|
-
def submitter
|
65
|
-
self.connection.users.get(submitter_id)
|
66
|
-
end
|
67
|
-
|
68
64
|
private
|
69
65
|
|
70
66
|
def params
|
71
|
-
Cistern::Hash.slice(Zendesk2.stringify_keys(attributes),
|
67
|
+
Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), *PARAMS)
|
72
68
|
end
|
73
69
|
|
74
70
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class Zendesk2::Client::Tickets < Cistern::Collection
|
2
2
|
include Zendesk2::PagedCollection
|
3
|
+
include Zendesk2::Searchable
|
3
4
|
|
4
5
|
model Zendesk2::Client::Ticket
|
5
6
|
|
@@ -7,12 +8,5 @@ class Zendesk2::Client::Tickets < Cistern::Collection
|
|
7
8
|
self.collection_root= "tickets"
|
8
9
|
self.model_method= :get_ticket
|
9
10
|
self.model_root= "ticket"
|
10
|
-
|
11
|
-
def search(term)
|
12
|
-
body = connection.search_ticket("query" => term).body
|
13
|
-
if data = body.delete("results")
|
14
|
-
load(data)
|
15
|
-
end
|
16
|
-
merge_attributes(body)
|
17
|
-
end
|
11
|
+
self.search_type= "ticket"
|
18
12
|
end
|
@@ -1,4 +1,8 @@
|
|
1
1
|
class Zendesk2::Client::User < Cistern::Model
|
2
|
+
extend Zendesk2::Attributes
|
3
|
+
|
4
|
+
PARAMS = %w[name email organization_id external_id alias verified locate_id time_zone phone signature details notes role custom_role_id moderator ticket_restriction only_private_comments]
|
5
|
+
|
2
6
|
identity :id, type: :id
|
3
7
|
attribute :url
|
4
8
|
attribute :external_id
|
@@ -29,6 +33,8 @@ class Zendesk2::Client::User < Cistern::Model
|
|
29
33
|
attribute :photo
|
30
34
|
attribute :authenticity_token
|
31
35
|
|
36
|
+
assoc_accessor :organization
|
37
|
+
|
32
38
|
def save
|
33
39
|
if new_record?
|
34
40
|
requires :name, :email
|
@@ -101,18 +107,10 @@ class Zendesk2::Client::User < Cistern::Model
|
|
101
107
|
connection.tickets.load(data)
|
102
108
|
end
|
103
109
|
|
104
|
-
def organization=(organization)
|
105
|
-
self.organization_id= organization.id
|
106
|
-
end
|
107
|
-
|
108
|
-
def organization
|
109
|
-
self.connection.organizations.get(self.organization_id)
|
110
|
-
end
|
111
|
-
|
112
110
|
private
|
113
111
|
|
114
112
|
def params
|
115
|
-
writable_attributes = Cistern::Hash.slice(Zendesk2.stringify_keys(attributes),
|
113
|
+
writable_attributes = Cistern::Hash.slice(Zendesk2.stringify_keys(attributes), *PARAMS)
|
116
114
|
writable_attributes.delete("organization_id") if writable_attributes["organization_id"] == 0
|
117
115
|
writable_attributes.delete("custom_role_id") if writable_attributes["custom_role_id"] == 0
|
118
116
|
writable_attributes
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class Zendesk2::Client::Users < Cistern::Collection
|
2
2
|
include Zendesk2::PagedCollection
|
3
|
+
include Zendesk2::Searchable
|
3
4
|
|
4
5
|
model Zendesk2::Client::User
|
5
6
|
|
@@ -7,16 +8,9 @@ class Zendesk2::Client::Users < Cistern::Collection
|
|
7
8
|
self.collection_root= "users"
|
8
9
|
self.model_method= :get_user
|
9
10
|
self.model_root= "user"
|
11
|
+
self.search_type= "user"
|
10
12
|
|
11
13
|
def current
|
12
14
|
new(connection.get_current_user.body["user"])
|
13
15
|
end
|
14
|
-
|
15
|
-
def search(term)
|
16
|
-
body = connection.search_user("query" => term).body
|
17
|
-
if data = body.delete("results")
|
18
|
-
load(data)
|
19
|
-
end
|
20
|
-
merge_attributes(body)
|
21
|
-
end
|
22
16
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def create_category(params={})
|
4
|
+
request(
|
5
|
+
:body => {"category" => params},
|
6
|
+
:method => :post,
|
7
|
+
:path => "/categories.json",
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end # Real
|
11
|
+
|
12
|
+
class Mock
|
13
|
+
def create_category(params={})
|
14
|
+
identity = self.class.new_id
|
15
|
+
|
16
|
+
record = {
|
17
|
+
"id" => identity,
|
18
|
+
"url" => url_for("/categories/#{identity}.json"),
|
19
|
+
"created_at" => Time.now.iso8601,
|
20
|
+
"updated_at" => Time.now.iso8601,
|
21
|
+
}.merge(params)
|
22
|
+
|
23
|
+
self.data[:categories][identity]= record
|
24
|
+
|
25
|
+
response(
|
26
|
+
:method => :post,
|
27
|
+
:body => {"category" => record},
|
28
|
+
:path => "/categories.json"
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end # Mock
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def create_forum(params={})
|
4
|
+
request(
|
5
|
+
:body => {"forum" => params},
|
6
|
+
:method => :post,
|
7
|
+
:path => "/forums.json",
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end # Real
|
11
|
+
|
12
|
+
class Mock
|
13
|
+
def create_forum(params={})
|
14
|
+
identity = self.class.new_id
|
15
|
+
|
16
|
+
record = {
|
17
|
+
"id" => identity,
|
18
|
+
"url" => url_for("/forums/#{identity}.json"),
|
19
|
+
"created_at" => Time.now.iso8601,
|
20
|
+
"updated_at" => Time.now.iso8601,
|
21
|
+
}.merge(params)
|
22
|
+
|
23
|
+
path = "/forums.json"
|
24
|
+
self.data[:forums][identity]= record
|
25
|
+
|
26
|
+
response(
|
27
|
+
:method => :post,
|
28
|
+
:body => {"forum" => record},
|
29
|
+
:path => path,
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end # Mock
|
33
|
+
end
|
@@ -21,13 +21,32 @@ class Zendesk2::Client
|
|
21
21
|
"active" => true,
|
22
22
|
}.merge(params)
|
23
23
|
|
24
|
-
|
24
|
+
path = "/users.json"
|
25
|
+
if record["email"] && self.data[:users].find{|k,u| u["email"] == record["email"] && k != identity}
|
26
|
+
response(
|
27
|
+
:method => :put,
|
28
|
+
:path => path,
|
29
|
+
:status => 422,
|
30
|
+
:body => {
|
31
|
+
"error" => "RecordInvalid",
|
32
|
+
"description" => "Record validation errors", "details" => {
|
33
|
+
"email" => [ {
|
34
|
+
"type" => "#{record["email"]} is already being used by another user",
|
35
|
+
"description" => "Email: #{record["email"]} is already being used by another user"
|
36
|
+
} ]
|
37
|
+
}
|
38
|
+
}
|
39
|
+
)
|
40
|
+
else
|
25
41
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
42
|
+
self.data[:users][identity]= record
|
43
|
+
|
44
|
+
response(
|
45
|
+
:method => :post,
|
46
|
+
:body => {"user" => record},
|
47
|
+
:path => path,
|
48
|
+
)
|
49
|
+
end
|
31
50
|
end
|
32
51
|
end # Mock
|
33
52
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def destroy_category(params={})
|
4
|
+
id = params["id"]
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :delete,
|
8
|
+
:path => "/categories/#{id}.json"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Mock
|
14
|
+
def destroy_category(params={})
|
15
|
+
id = params["id"]
|
16
|
+
body = self.data[:categories].delete(id)
|
17
|
+
|
18
|
+
response(
|
19
|
+
:method => :delete,
|
20
|
+
:path => "/categories/#{id}.json",
|
21
|
+
:body => {
|
22
|
+
"category" => body,
|
23
|
+
},
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def destroy_forum(params={})
|
4
|
+
id = params["id"]
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :delete,
|
8
|
+
:path => "/forums/#{id}.json"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Mock
|
14
|
+
def destroy_forum(params={})
|
15
|
+
id = params["id"]
|
16
|
+
path = "/forums/#{id}.json"
|
17
|
+
|
18
|
+
body = self.data[:forums].delete(id)
|
19
|
+
response(
|
20
|
+
:method => :delete,
|
21
|
+
:path => path,
|
22
|
+
:body => {
|
23
|
+
"forum" => body,
|
24
|
+
},
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def get_categories(params={})
|
4
|
+
page_params = Zendesk2.paging_parameters(params)
|
5
|
+
|
6
|
+
request(
|
7
|
+
:params => page_params,
|
8
|
+
:method => :get,
|
9
|
+
:path => "/categories.json",
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class Mock
|
14
|
+
def get_categories(params={})
|
15
|
+
page(params, :categories, "/categories.json", "categories")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def get_category(params={})
|
4
|
+
id = params["id"]
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :get,
|
8
|
+
:path => "/categories/#{id}.json"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end # Real
|
12
|
+
|
13
|
+
class Mock
|
14
|
+
def get_category(params={})
|
15
|
+
id = params["id"]
|
16
|
+
if body = self.data[:categories][id]
|
17
|
+
|
18
|
+
response(
|
19
|
+
:path => "/categories/#{id}.json",
|
20
|
+
:body => {
|
21
|
+
"category" => body
|
22
|
+
},
|
23
|
+
)
|
24
|
+
else
|
25
|
+
response(
|
26
|
+
:path => "/categories/#{id}.json",
|
27
|
+
:status => 404
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end # Mock
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def get_forum(params={})
|
4
|
+
id = params["id"]
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :get,
|
8
|
+
:path => "/forums/#{id}.json"
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end # Real
|
12
|
+
|
13
|
+
class Mock
|
14
|
+
def get_forum(params={})
|
15
|
+
id = params["id"]
|
16
|
+
body = self.data[:forums][id]
|
17
|
+
|
18
|
+
response(
|
19
|
+
:path => "/forums/#{id}.json",
|
20
|
+
:body => {
|
21
|
+
"forum" => body
|
22
|
+
},
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end # Mock
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def get_forums(params={})
|
4
|
+
page_params = Zendesk2.paging_parameters(params)
|
5
|
+
|
6
|
+
request(
|
7
|
+
:params => page_params,
|
8
|
+
:method => :get,
|
9
|
+
:path => "/forums.json",
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class Mock
|
14
|
+
def get_forums(params={})
|
15
|
+
page(params, :forums, "/forums.json", "forums")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -4,7 +4,7 @@ class Zendesk2::Client
|
|
4
4
|
term = query.map{|k,v| "#{k}:#{v}"}.join(" ")
|
5
5
|
request(
|
6
6
|
:method => :get,
|
7
|
-
:params => {query: term},
|
7
|
+
:params => {query: "\"#{term}\""},
|
8
8
|
:path => "/search.json",
|
9
9
|
)
|
10
10
|
end
|
@@ -13,7 +13,7 @@ class Zendesk2::Client
|
|
13
13
|
class Mock
|
14
14
|
def search(query)
|
15
15
|
type = query.delete("type")
|
16
|
-
collection = type.nil? ? self.data.values : self.data[
|
16
|
+
collection = type.nil? ? self.data.values : self.data[pluralize(type).to_sym]
|
17
17
|
|
18
18
|
results = collection.select{|k,v| query.all?{|term, condition| v[term.to_s] == condition}}.values
|
19
19
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def update_category(params={})
|
4
|
+
id = params.delete("id")
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :put,
|
8
|
+
:path => "/categories/#{id}.json",
|
9
|
+
:body => {
|
10
|
+
"category" => params
|
11
|
+
},
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Mock
|
16
|
+
def update_category(params={})
|
17
|
+
id = params.delete("id")
|
18
|
+
body = self.data[:categories][id].merge!(params)
|
19
|
+
|
20
|
+
response(
|
21
|
+
:method => :put,
|
22
|
+
:path => "/categories/#{id}.json",
|
23
|
+
:body => {
|
24
|
+
"category" => body
|
25
|
+
},
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Zendesk2::Client
|
2
|
+
class Real
|
3
|
+
def update_forum(params={})
|
4
|
+
id = params.delete("id")
|
5
|
+
|
6
|
+
request(
|
7
|
+
:method => :put,
|
8
|
+
:path => "/forums/#{id}.json",
|
9
|
+
:body => {
|
10
|
+
"forum" => params
|
11
|
+
},
|
12
|
+
)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
class Mock
|
16
|
+
def update_forum(params={})
|
17
|
+
id = params.delete("id")
|
18
|
+
path = "/forums/#{id}.json"
|
19
|
+
|
20
|
+
body = self.data[:forums][id].merge!(params)
|
21
|
+
response(
|
22
|
+
:method => :put,
|
23
|
+
:path => path,
|
24
|
+
:body => {
|
25
|
+
"forum" => body
|
26
|
+
},
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -15,15 +15,32 @@ class Zendesk2::Client
|
|
15
15
|
class Mock
|
16
16
|
def update_user(params={})
|
17
17
|
id = params.delete("id")
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
path = "/users/#{id}.json"
|
19
|
+
if params["email"] && self.data[:users].find{|k,u| u["email"] == params["email"] && k != id}
|
20
|
+
response(
|
21
|
+
:method => :put,
|
22
|
+
:path => path,
|
23
|
+
:status => 422,
|
24
|
+
:body => {
|
25
|
+
"error" => "RecordInvalid",
|
26
|
+
"description" => "Record validation errors", "details" => {
|
27
|
+
"email" => [ {
|
28
|
+
"type" => "#{params["email"]} is already being used by another user",
|
29
|
+
"description" => "Email: #{params["email"]} is already being used by another user"
|
30
|
+
} ]
|
31
|
+
}
|
32
|
+
}
|
33
|
+
)
|
34
|
+
else
|
35
|
+
body = self.data[:users][id].merge!(params)
|
36
|
+
response(
|
37
|
+
:method => :put,
|
38
|
+
:path => path,
|
39
|
+
:body => {
|
40
|
+
"user" => body
|
41
|
+
},
|
42
|
+
)
|
43
|
+
end
|
27
44
|
end
|
28
45
|
end
|
29
46
|
end
|
data/lib/zendesk2/client.rb
CHANGED
@@ -3,6 +3,10 @@ class Zendesk2::Client < Cistern::Service
|
|
3
3
|
model_path "zendesk2/client/models"
|
4
4
|
request_path "zendesk2/client/requests"
|
5
5
|
|
6
|
+
model :category
|
7
|
+
collection :categories
|
8
|
+
model :forum
|
9
|
+
collection :forums
|
6
10
|
model :organization
|
7
11
|
collection :organizations
|
8
12
|
model :ticket
|
@@ -10,24 +14,34 @@ class Zendesk2::Client < Cistern::Service
|
|
10
14
|
model :user
|
11
15
|
collection :users
|
12
16
|
|
17
|
+
request :create_category
|
18
|
+
request :create_forum
|
13
19
|
request :create_organization
|
14
20
|
request :create_ticket
|
15
21
|
request :create_user
|
22
|
+
request :destroy_category
|
23
|
+
request :destroy_forum
|
16
24
|
request :destroy_organization
|
17
25
|
request :destroy_ticket
|
18
26
|
request :destroy_user
|
19
27
|
request :get_current_user
|
28
|
+
request :get_category
|
29
|
+
request :get_forum
|
20
30
|
request :get_organization
|
21
31
|
request :get_organization_tickets
|
22
32
|
request :get_organization_users
|
23
33
|
request :get_ticket
|
24
34
|
request :get_user
|
35
|
+
request :get_categories
|
36
|
+
request :get_forums
|
25
37
|
request :get_organizations
|
26
38
|
request :get_requested_tickets
|
27
39
|
request :get_ccd_tickets
|
28
40
|
request :get_tickets
|
29
41
|
request :get_users
|
30
42
|
request :search
|
43
|
+
request :update_category
|
44
|
+
request :update_forum
|
31
45
|
request :update_organization
|
32
46
|
request :update_ticket
|
33
47
|
request :update_user
|
@@ -36,7 +50,7 @@ class Zendesk2::Client < Cistern::Service
|
|
36
50
|
|
37
51
|
class Real
|
38
52
|
|
39
|
-
|
53
|
+
attr_accessor :username, :url, :token, :logger
|
40
54
|
|
41
55
|
def initialize(options={})
|
42
56
|
url = options[:url] || begin
|
@@ -52,7 +66,7 @@ class Zendesk2::Client < Cistern::Service
|
|
52
66
|
|
53
67
|
@url = URI.parse(url).to_s
|
54
68
|
|
55
|
-
logger
|
69
|
+
@logger = options[:logger] || Logger.new(nil)
|
56
70
|
adapter = options[:adapter] || :net_http
|
57
71
|
connection_options = options[:connection_options] || {ssl: {verify: false}}
|
58
72
|
@username = options[:username] || Zendesk2.defaults[:username]
|
@@ -65,13 +79,13 @@ class Zendesk2::Client < Cistern::Service
|
|
65
79
|
# response
|
66
80
|
builder.use Faraday::Request::BasicAuthentication, @username, password
|
67
81
|
builder.use Faraday::Response::RaiseError
|
68
|
-
builder.use Zendesk2::Logger, logger if logger
|
69
82
|
builder.response :json
|
70
83
|
|
71
84
|
# request
|
72
85
|
builder.request :multipart
|
73
86
|
builder.request :json
|
74
87
|
|
88
|
+
builder.use Zendesk2::Logger, @logger
|
75
89
|
builder.adapter adapter
|
76
90
|
end
|
77
91
|
end
|
@@ -103,6 +117,8 @@ class Zendesk2::Client < Cistern::Service
|
|
103
117
|
:users => {},
|
104
118
|
:organizations => {},
|
105
119
|
:tickets => {},
|
120
|
+
:forums => {},
|
121
|
+
:categories => {},
|
106
122
|
}
|
107
123
|
end
|
108
124
|
|
@@ -181,6 +197,11 @@ class Zendesk2::Client < Cistern::Service
|
|
181
197
|
)
|
182
198
|
end
|
183
199
|
|
200
|
+
def pluralize(word)
|
201
|
+
[[/y$/, 'ies'], [/$/, 's']].find{|regex, replace| word.gsub!(regex, replace) if word.match(regex)}
|
202
|
+
word
|
203
|
+
end
|
204
|
+
|
184
205
|
def response(options={})
|
185
206
|
method = options[:method] || :get
|
186
207
|
status = options[:status] || 200
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Zendesk2::Searchable
|
2
|
+
def self.included(klass)
|
3
|
+
klass.send(:extend, Zendesk2::Searchable::Attributes)
|
4
|
+
end
|
5
|
+
|
6
|
+
def search(parameters)
|
7
|
+
body = connection.search(parameters.merge("type" => self.class.search_type)).body
|
8
|
+
if data = body.delete("results")
|
9
|
+
load(data)
|
10
|
+
end
|
11
|
+
merge_attributes(body)
|
12
|
+
end
|
13
|
+
|
14
|
+
module Attributes
|
15
|
+
attr_accessor :search_type
|
16
|
+
end
|
17
|
+
end
|
data/lib/zendesk2/version.rb
CHANGED
data/lib/zendesk2.rb
CHANGED
@@ -8,11 +8,14 @@ require 'faraday_middleware'
|
|
8
8
|
|
9
9
|
# stdlib
|
10
10
|
require 'time'
|
11
|
+
require 'logger'
|
11
12
|
|
12
13
|
module Zendesk2
|
14
|
+
autoload :Attributes, 'zendesk2/attributes'
|
13
15
|
autoload :Error, 'zendesk2/error'
|
14
16
|
autoload :Client, 'zendesk2/client'
|
15
17
|
autoload :PagedCollection, 'zendesk2/paged_collection'
|
18
|
+
autoload :Searchable, 'zendesk2/searchable'
|
16
19
|
autoload :Logger, 'zendesk2/logger'
|
17
20
|
|
18
21
|
def self.defaults
|
data/spec/forums_spec.rb
ADDED
data/spec/shared/resource.rb
CHANGED
@@ -12,6 +12,7 @@ shared_examples "a resource" do |_collection, _params, _update_params|
|
|
12
12
|
before(:each) do
|
13
13
|
2.times.each { collection.create(instance_exec(&_params)) }
|
14
14
|
end
|
15
|
+
|
15
16
|
it "by retrieving the first page" do
|
16
17
|
collection.all("per_page" => "1").size.should == 1
|
17
18
|
end
|
@@ -42,11 +43,17 @@ shared_examples "a resource" do |_collection, _params, _update_params|
|
|
42
43
|
end
|
43
44
|
|
44
45
|
it "by destroy a record" do
|
46
|
+
pending if _collection == :forums
|
45
47
|
record = collection.create(params)
|
46
48
|
record.identity.should_not be_nil
|
47
49
|
record.destroy
|
48
50
|
record.should be_destroyed
|
49
51
|
end
|
50
52
|
|
51
|
-
|
53
|
+
# Search index takes 2-3 minutes according to the docs
|
54
|
+
it "should search" do
|
55
|
+
pending unless Zendesk2::Client.mocking?
|
56
|
+
record = collection.create(params)
|
57
|
+
collection.search(params).should include(record)
|
58
|
+
end
|
52
59
|
end
|
data/spec/users_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe "users" do
|
|
5
5
|
it_should_behave_like "a resource",
|
6
6
|
:users,
|
7
7
|
lambda { {email: "zendesk2+#{Zendesk2.uuid}@example.org", name: Zendesk2.uuid, verified: true} },
|
8
|
-
|
8
|
+
lambda { {name: Zendesk2.uuid} }
|
9
9
|
|
10
10
|
it "should get current user" do
|
11
11
|
current_user = client.users.current
|
@@ -15,6 +15,14 @@ describe "users" do
|
|
15
15
|
|
16
16
|
describe do
|
17
17
|
let(:user) { client.users.create(email: "zendesk2+#{Zendesk2.uuid}@example.org", name: Zendesk2.uuid) }
|
18
|
+
after(:all) { user.destroy }
|
19
|
+
|
20
|
+
it "should update organization" do
|
21
|
+
organization = client.organizations.create(name: Zendesk2.uuid)
|
22
|
+
user.organization= organization
|
23
|
+
user.save.should be_true
|
24
|
+
user.organization.should == organization
|
25
|
+
end
|
18
26
|
|
19
27
|
it "should get requested tickets" do
|
20
28
|
ticket = client.tickets.create(requester: user, subject: Zendesk2.uuid, description: Zendesk2.uuid)
|
@@ -36,6 +44,12 @@ describe "users" do
|
|
36
44
|
user.should_not be_destroyed
|
37
45
|
end
|
38
46
|
|
47
|
+
it "should hate non-unique emails" do
|
48
|
+
email = "zendesk2+#{Zendesk2.uuid}@example.org"
|
49
|
+
client.users.create(email: email, name: Zendesk2.uuid)
|
50
|
+
lambda { client.users.create(email: email, name: Zendesk2.uuid) }.should raise_exception(Zendesk2::Error)
|
51
|
+
end
|
52
|
+
|
39
53
|
it "should form login url"
|
40
54
|
end
|
41
55
|
end
|
data/zendesk2.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = ["me@joshualane.com"]
|
7
7
|
gem.description = %q{Zendesk V2 API client}
|
8
8
|
gem.summary = %q{Zendesk V2 API client}
|
9
|
-
gem.homepage = ""
|
9
|
+
gem.homepage = "http://joshualane.com/zendesk2"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: cistern
|
@@ -91,21 +91,34 @@ files:
|
|
91
91
|
- README.md
|
92
92
|
- Rakefile
|
93
93
|
- lib/zendesk2.rb
|
94
|
+
- lib/zendesk2/attributes.rb
|
94
95
|
- lib/zendesk2/client.rb
|
96
|
+
- lib/zendesk2/client/models/categories.rb
|
97
|
+
- lib/zendesk2/client/models/category.rb
|
98
|
+
- lib/zendesk2/client/models/forum.rb
|
99
|
+
- lib/zendesk2/client/models/forums.rb
|
95
100
|
- lib/zendesk2/client/models/organization.rb
|
96
101
|
- lib/zendesk2/client/models/organizations.rb
|
97
102
|
- lib/zendesk2/client/models/ticket.rb
|
98
103
|
- lib/zendesk2/client/models/tickets.rb
|
99
104
|
- lib/zendesk2/client/models/user.rb
|
100
105
|
- lib/zendesk2/client/models/users.rb
|
106
|
+
- lib/zendesk2/client/requests/create_category.rb
|
107
|
+
- lib/zendesk2/client/requests/create_forum.rb
|
101
108
|
- lib/zendesk2/client/requests/create_organization.rb
|
102
109
|
- lib/zendesk2/client/requests/create_ticket.rb
|
103
110
|
- lib/zendesk2/client/requests/create_user.rb
|
111
|
+
- lib/zendesk2/client/requests/destroy_category.rb
|
112
|
+
- lib/zendesk2/client/requests/destroy_forum.rb
|
104
113
|
- lib/zendesk2/client/requests/destroy_organization.rb
|
105
114
|
- lib/zendesk2/client/requests/destroy_ticket.rb
|
106
115
|
- lib/zendesk2/client/requests/destroy_user.rb
|
116
|
+
- lib/zendesk2/client/requests/get_categories.rb
|
117
|
+
- lib/zendesk2/client/requests/get_category.rb
|
107
118
|
- lib/zendesk2/client/requests/get_ccd_tickets.rb
|
108
119
|
- lib/zendesk2/client/requests/get_current_user.rb
|
120
|
+
- lib/zendesk2/client/requests/get_forum.rb
|
121
|
+
- lib/zendesk2/client/requests/get_forums.rb
|
109
122
|
- lib/zendesk2/client/requests/get_organization.rb
|
110
123
|
- lib/zendesk2/client/requests/get_organization_tickets.rb
|
111
124
|
- lib/zendesk2/client/requests/get_organization_users.rb
|
@@ -116,13 +129,18 @@ files:
|
|
116
129
|
- lib/zendesk2/client/requests/get_user.rb
|
117
130
|
- lib/zendesk2/client/requests/get_users.rb
|
118
131
|
- lib/zendesk2/client/requests/search.rb
|
132
|
+
- lib/zendesk2/client/requests/update_category.rb
|
133
|
+
- lib/zendesk2/client/requests/update_forum.rb
|
119
134
|
- lib/zendesk2/client/requests/update_organization.rb
|
120
135
|
- lib/zendesk2/client/requests/update_ticket.rb
|
121
136
|
- lib/zendesk2/client/requests/update_user.rb
|
122
137
|
- lib/zendesk2/error.rb
|
123
138
|
- lib/zendesk2/logger.rb
|
124
139
|
- lib/zendesk2/paged_collection.rb
|
140
|
+
- lib/zendesk2/searchable.rb
|
125
141
|
- lib/zendesk2/version.rb
|
142
|
+
- spec/categories_spec.rb
|
143
|
+
- spec/forums_spec.rb
|
126
144
|
- spec/organizations_spec.rb
|
127
145
|
- spec/shared/resource.rb
|
128
146
|
- spec/spec_helper.rb
|
@@ -130,7 +148,7 @@ files:
|
|
130
148
|
- spec/tickets_spec.rb
|
131
149
|
- spec/users_spec.rb
|
132
150
|
- zendesk2.gemspec
|
133
|
-
homepage:
|
151
|
+
homepage: http://joshualane.com/zendesk2
|
134
152
|
licenses: []
|
135
153
|
post_install_message:
|
136
154
|
rdoc_options: []
|
@@ -155,6 +173,8 @@ signing_key:
|
|
155
173
|
specification_version: 3
|
156
174
|
summary: Zendesk V2 API client
|
157
175
|
test_files:
|
176
|
+
- spec/categories_spec.rb
|
177
|
+
- spec/forums_spec.rb
|
158
178
|
- spec/organizations_spec.rb
|
159
179
|
- spec/shared/resource.rb
|
160
180
|
- spec/spec_helper.rb
|