zendesk2 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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