zendesk2 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/README.md +30 -25
  2. data/lib/zendesk2/attributes.rb +23 -0
  3. data/lib/zendesk2/client/models/categories.rb +12 -0
  4. data/lib/zendesk2/client/models/category.rb +38 -0
  5. data/lib/zendesk2/client/models/forum.rb +50 -0
  6. data/lib/zendesk2/client/models/forums.rb +12 -0
  7. data/lib/zendesk2/client/models/organization.rb +3 -1
  8. data/lib/zendesk2/client/models/organizations.rb +2 -12
  9. data/lib/zendesk2/client/models/ticket.rb +9 -13
  10. data/lib/zendesk2/client/models/tickets.rb +2 -8
  11. data/lib/zendesk2/client/models/user.rb +7 -9
  12. data/lib/zendesk2/client/models/users.rb +2 -8
  13. data/lib/zendesk2/client/requests/create_category.rb +32 -0
  14. data/lib/zendesk2/client/requests/create_forum.rb +33 -0
  15. data/lib/zendesk2/client/requests/create_user.rb +25 -6
  16. data/lib/zendesk2/client/requests/destroy_category.rb +27 -0
  17. data/lib/zendesk2/client/requests/destroy_forum.rb +28 -0
  18. data/lib/zendesk2/client/requests/get_categories.rb +18 -0
  19. data/lib/zendesk2/client/requests/get_category.rb +32 -0
  20. data/lib/zendesk2/client/requests/get_forum.rb +26 -0
  21. data/lib/zendesk2/client/requests/get_forums.rb +18 -0
  22. data/lib/zendesk2/client/requests/search.rb +2 -2
  23. data/lib/zendesk2/client/requests/update_category.rb +29 -0
  24. data/lib/zendesk2/client/requests/update_forum.rb +30 -0
  25. data/lib/zendesk2/client/requests/update_user.rb +26 -9
  26. data/lib/zendesk2/client.rb +24 -3
  27. data/lib/zendesk2/searchable.rb +17 -0
  28. data/lib/zendesk2/version.rb +1 -1
  29. data/lib/zendesk2.rb +3 -0
  30. data/spec/categories_spec.rb +9 -0
  31. data/spec/forums_spec.rb +9 -0
  32. data/spec/shared/resource.rb +8 -1
  33. data/spec/users_spec.rb +15 -1
  34. data/zendesk2.gemspec +1 -1
  35. 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
- :subdomain: zendeskdev
25
- :username: zendeskedge@example.com
26
- :password: wickedsecurepassword
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
- Zendesk2::Client.new(subdomain: "engineyard", username: "orchestra", password: "gwoo")
33
- => #<Zendesk2::Client::Real:0x007f99da1f9430 @url="https://engineyard.zendesk.com/api/v2", @username="orchestra", @password="gwoo", …>
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
- => #<Zendesk2::Client::Real:0x007fd1bae486b0 @url="http://support.cloud.engineyard.com", @username="mate", @password="bambilla", …>
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
- client.users.all
52
- => <Zendesk2::Client::Users
53
- count=1779,
54
- next_page_link="https://dev.zendesk.com/api/v2/users.json?page=2",
55
- previous_page_link=nil
56
- [
57
- <Zendesk2::Client::User
58
- id=125394183,
59
- url="https://dev.zendesk.com/api/v2/users/125394183.json",
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), "id", "details", "domain_names", "external_id", "group_id", "shared_comments", "shared_tickets", "tags", "name", "notes")
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), "external_id", "via", "requester_id", "submitter_id", "assignee_id", "organization_id", "subject", "description", "fields", "recipient", "status", "collaborator_ids")
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), "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")
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
- self.data[:users][identity]= record
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
- response(
27
- :method => :post,
28
- :body => {"user" => record},
29
- :path => "/users.json"
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["#{type}s".to_sym]
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
- body = self.data[:users][id].merge!(params)
19
-
20
- response(
21
- :method => :put,
22
- :path => "/users/#{id}.json",
23
- :body => {
24
- "user" => body
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
@@ -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
- attr_reader :username, :url, :token
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 = options[: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
@@ -1,3 +1,3 @@
1
1
  module Zendesk2
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
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
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe "categories" do
4
+ let(:client) { create_client }
5
+ it_should_behave_like "a resource",
6
+ :categories,
7
+ lambda { {name: Zendesk2.uuid} },
8
+ lambda { {name: Zendesk2.uuid} }
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe "forums" do
4
+ let(:client) { create_client }
5
+ it_should_behave_like "a resource",
6
+ :forums,
7
+ lambda { {name: Zendesk2.uuid} },
8
+ lambda { {name: Zendesk2.uuid} }
9
+ end
@@ -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
- it "should search"
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
- lambda { {name: Zendesk2.uuid} }
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.13
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 00:00:00.000000000 Z
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