zendesk2 1.9.0 → 1.10.0
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +30 -0
- data/.travis.yml +3 -1
- data/Gemfile +4 -5
- data/Guardfile +4 -3
- data/Rakefile +4 -3
- data/lib/zendesk2.rb +9 -6
- data/lib/zendesk2/attributes.rb +11 -8
- data/lib/zendesk2/audit_event.rb +5 -3
- data/lib/zendesk2/categories.rb +4 -3
- data/lib/zendesk2/category.rb +10 -5
- data/lib/zendesk2/client.rb +3 -3
- data/lib/zendesk2/collection.rb +35 -21
- data/lib/zendesk2/create_category.rb +10 -9
- data/lib/zendesk2/create_forum.rb +11 -10
- data/lib/zendesk2/create_group.rb +13 -12
- data/lib/zendesk2/create_membership.rb +21 -20
- data/lib/zendesk2/create_organization.rb +24 -18
- data/lib/zendesk2/create_ticket.rb +60 -56
- data/lib/zendesk2/create_ticket_field.rb +24 -22
- data/lib/zendesk2/create_topic.rb +11 -10
- data/lib/zendesk2/create_topic_comment.rb +12 -11
- data/lib/zendesk2/create_user.rb +54 -41
- data/lib/zendesk2/create_user_field.rb +22 -21
- data/lib/zendesk2/create_user_identity.rb +18 -15
- data/lib/zendesk2/create_view.rb +62 -62
- data/lib/zendesk2/destroy_category.rb +2 -1
- data/lib/zendesk2/destroy_forum.rb +2 -1
- data/lib/zendesk2/destroy_group.rb +3 -2
- data/lib/zendesk2/destroy_membership.rb +7 -5
- data/lib/zendesk2/destroy_organization.rb +3 -2
- data/lib/zendesk2/destroy_ticket.rb +3 -2
- data/lib/zendesk2/destroy_ticket_field.rb +3 -2
- data/lib/zendesk2/destroy_topic.rb +3 -2
- data/lib/zendesk2/destroy_topic_comment.rb +4 -3
- data/lib/zendesk2/destroy_user.rb +11 -10
- data/lib/zendesk2/destroy_user_field.rb +3 -2
- data/lib/zendesk2/destroy_user_identity.rb +4 -3
- data/lib/zendesk2/destroy_view.rb +3 -2
- data/lib/zendesk2/error.rb +1 -1
- data/lib/zendesk2/forum.rb +36 -18
- data/lib/zendesk2/forums.rb +4 -3
- data/lib/zendesk2/get_assignable_groups.rb +3 -2
- data/lib/zendesk2/get_categories.rb +2 -1
- data/lib/zendesk2/get_category.rb +3 -2
- data/lib/zendesk2/get_ccd_tickets.rb +4 -3
- data/lib/zendesk2/get_current_user.rb +3 -2
- data/lib/zendesk2/get_forum.rb +3 -2
- data/lib/zendesk2/get_forums.rb +2 -1
- data/lib/zendesk2/get_group.rb +3 -2
- data/lib/zendesk2/get_groups.rb +2 -1
- data/lib/zendesk2/get_membership.rb +3 -2
- data/lib/zendesk2/get_memberships.rb +3 -2
- data/lib/zendesk2/get_organization.rb +3 -2
- data/lib/zendesk2/get_organization_by_external_id.rb +8 -5
- data/lib/zendesk2/get_organization_memberships.rb +5 -2
- data/lib/zendesk2/get_organization_tickets.rb +7 -5
- data/lib/zendesk2/get_organization_users.rb +6 -5
- data/lib/zendesk2/get_organizations.rb +2 -1
- data/lib/zendesk2/get_requested_tickets.rb +5 -4
- data/lib/zendesk2/get_ticket.rb +3 -2
- data/lib/zendesk2/get_ticket_audit.rb +5 -4
- data/lib/zendesk2/get_ticket_audits.rb +4 -3
- data/lib/zendesk2/get_ticket_comments.rb +6 -5
- data/lib/zendesk2/get_ticket_field.rb +3 -2
- data/lib/zendesk2/get_ticket_fields.rb +2 -1
- data/lib/zendesk2/get_ticket_metric.rb +4 -3
- data/lib/zendesk2/get_ticket_metrics.rb +3 -2
- data/lib/zendesk2/get_tickets.rb +2 -1
- data/lib/zendesk2/get_topic.rb +3 -2
- data/lib/zendesk2/get_topic_comment.rb +4 -3
- data/lib/zendesk2/get_topic_comments.rb +5 -4
- data/lib/zendesk2/get_topics.rb +2 -1
- data/lib/zendesk2/get_user.rb +7 -7
- data/lib/zendesk2/get_user_field.rb +3 -2
- data/lib/zendesk2/get_user_fields.rb +3 -2
- data/lib/zendesk2/get_user_identities.rb +4 -3
- data/lib/zendesk2/get_user_identity.rb +4 -3
- data/lib/zendesk2/get_user_memberships.rb +4 -3
- data/lib/zendesk2/get_user_organizations.rb +5 -4
- data/lib/zendesk2/get_users.rb +3 -2
- data/lib/zendesk2/get_view.rb +3 -2
- data/lib/zendesk2/get_view_tickets.rb +19 -16
- data/lib/zendesk2/get_views.rb +2 -1
- data/lib/zendesk2/group.rb +6 -5
- data/lib/zendesk2/groups.rb +7 -6
- data/lib/zendesk2/help_center.rb +15 -0
- data/lib/zendesk2/help_center/access_policy.rb +3 -2
- data/lib/zendesk2/help_center/article.rb +10 -7
- data/lib/zendesk2/help_center/articles.rb +7 -7
- data/lib/zendesk2/help_center/categories.rb +3 -2
- data/lib/zendesk2/help_center/category.rb +8 -7
- data/lib/zendesk2/help_center/create_help_center_article.rb +31 -29
- data/lib/zendesk2/help_center/create_help_center_category.rb +17 -16
- data/lib/zendesk2/help_center/create_help_center_post.rb +37 -0
- data/lib/zendesk2/help_center/create_help_center_section.rb +32 -31
- data/lib/zendesk2/help_center/create_help_center_topic.rb +36 -0
- data/lib/zendesk2/help_center/create_help_center_translation.rb +15 -14
- data/lib/zendesk2/help_center/destroy_help_center_article.rb +3 -2
- data/lib/zendesk2/help_center/destroy_help_center_category.rb +3 -2
- data/lib/zendesk2/help_center/destroy_help_center_post.rb +15 -0
- data/lib/zendesk2/help_center/destroy_help_center_section.rb +3 -2
- data/lib/zendesk2/help_center/destroy_help_center_topic.rb +15 -0
- data/lib/zendesk2/help_center/destroy_help_center_translation.rb +2 -1
- data/lib/zendesk2/help_center/get_help_center_access_policy.rb +6 -5
- data/lib/zendesk2/help_center/get_help_center_article.rb +7 -9
- data/lib/zendesk2/help_center/get_help_center_articles.rb +3 -2
- data/lib/zendesk2/help_center/get_help_center_categories.rb +6 -2
- data/lib/zendesk2/help_center/get_help_center_categories_articles.rb +8 -7
- data/lib/zendesk2/help_center/get_help_center_categories_sections.rb +6 -5
- data/lib/zendesk2/help_center/get_help_center_category.rb +7 -9
- data/lib/zendesk2/help_center/get_help_center_post.rb +19 -0
- data/lib/zendesk2/help_center/get_help_center_posts.rb +28 -0
- data/lib/zendesk2/help_center/get_help_center_section.rb +8 -10
- data/lib/zendesk2/help_center/get_help_center_sections.rb +3 -2
- data/lib/zendesk2/help_center/get_help_center_sections_articles.rb +9 -8
- data/lib/zendesk2/help_center/get_help_center_topic.rb +14 -0
- data/lib/zendesk2/help_center/get_help_center_topics.rb +10 -0
- data/lib/zendesk2/help_center/get_help_center_translation.rb +5 -4
- data/lib/zendesk2/help_center/get_help_center_translations.rb +7 -6
- data/lib/zendesk2/help_center/post.rb +72 -0
- data/lib/zendesk2/help_center/posts.rb +18 -0
- data/lib/zendesk2/help_center/search_help_center_articles.rb +8 -7
- data/lib/zendesk2/help_center/section.rb +11 -11
- data/lib/zendesk2/help_center/sections.rb +7 -6
- data/lib/zendesk2/help_center/topic.rb +52 -0
- data/lib/zendesk2/help_center/topics.rb +13 -0
- data/lib/zendesk2/help_center/translation.rb +8 -5
- data/lib/zendesk2/help_center/translation_source.rb +16 -13
- data/lib/zendesk2/help_center/translations.rb +3 -2
- data/lib/zendesk2/help_center/update_help_center_access_policy.rb +8 -7
- data/lib/zendesk2/help_center/update_help_center_article.rb +9 -11
- data/lib/zendesk2/help_center/update_help_center_category.rb +9 -11
- data/lib/zendesk2/help_center/update_help_center_post.rb +20 -0
- data/lib/zendesk2/help_center/update_help_center_section.rb +9 -11
- data/lib/zendesk2/help_center/update_help_center_topic.rb +20 -0
- data/lib/zendesk2/help_center/update_help_center_translation.rb +4 -3
- data/lib/zendesk2/logger.rb +3 -2
- data/lib/zendesk2/mark_membership_default.rb +7 -6
- data/lib/zendesk2/mark_user_identity_primary.rb +7 -6
- data/lib/zendesk2/membership.rb +10 -8
- data/lib/zendesk2/memberships.rb +18 -12
- data/lib/zendesk2/mock.rb +39 -34
- data/lib/zendesk2/model.rb +14 -3
- data/lib/zendesk2/organization.rb +7 -7
- data/lib/zendesk2/organizations.rb +14 -12
- data/lib/zendesk2/paged_collection.rb +40 -36
- data/lib/zendesk2/rate_limit.rb +4 -3
- data/lib/zendesk2/real.rb +25 -22
- data/lib/zendesk2/request.rb +78 -82
- data/lib/zendesk2/search.rb +8 -7
- data/lib/zendesk2/search_organization.rb +14 -14
- data/lib/zendesk2/search_user.rb +41 -37
- data/lib/zendesk2/searchable.rb +36 -26
- data/lib/zendesk2/ticket.rb +20 -18
- data/lib/zendesk2/ticket_audit.rb +5 -4
- data/lib/zendesk2/ticket_audits.rb +10 -11
- data/lib/zendesk2/ticket_change.rb +10 -11
- data/lib/zendesk2/ticket_comment.rb +2 -1
- data/lib/zendesk2/ticket_comment_privacy_change.rb +12 -14
- data/lib/zendesk2/ticket_comments.rb +7 -6
- data/lib/zendesk2/ticket_create.rb +8 -9
- data/lib/zendesk2/ticket_field.rb +5 -4
- data/lib/zendesk2/ticket_fields.rb +4 -3
- data/lib/zendesk2/ticket_metric.rb +2 -2
- data/lib/zendesk2/ticket_metrics.rb +3 -2
- data/lib/zendesk2/ticket_notification.rb +12 -13
- data/lib/zendesk2/ticket_voice_comment.rb +28 -29
- data/lib/zendesk2/tickets.rb +8 -7
- data/lib/zendesk2/topic.rb +49 -22
- data/lib/zendesk2/topic_comment.rb +12 -9
- data/lib/zendesk2/topic_comments.rb +4 -3
- data/lib/zendesk2/topics.rb +4 -3
- data/lib/zendesk2/update_category.rb +8 -6
- data/lib/zendesk2/update_forum.rb +5 -4
- data/lib/zendesk2/update_group.rb +5 -4
- data/lib/zendesk2/update_organization.rb +18 -9
- data/lib/zendesk2/update_request.rb +6 -5
- data/lib/zendesk2/update_ticket.rb +39 -38
- data/lib/zendesk2/update_ticket_field.rb +5 -4
- data/lib/zendesk2/update_topic.rb +5 -4
- data/lib/zendesk2/update_user.rb +39 -31
- data/lib/zendesk2/update_user_field.rb +4 -3
- data/lib/zendesk2/update_user_identity.rb +7 -6
- data/lib/zendesk2/update_view.rb +38 -34
- data/lib/zendesk2/user.rb +41 -37
- data/lib/zendesk2/user_field.rb +9 -6
- data/lib/zendesk2/user_fields.rb +4 -3
- data/lib/zendesk2/user_identities.rb +4 -3
- data/lib/zendesk2/user_identity.rb +12 -9
- data/lib/zendesk2/users.rb +5 -4
- data/lib/zendesk2/version.rb +2 -1
- data/lib/zendesk2/view.rb +24 -13
- data/lib/zendesk2/views.rb +3 -2
- data/spec/categories_spec.rb +63 -60
- data/spec/client_spec.rb +6 -5
- data/spec/forums_spec.rb +64 -61
- data/spec/groups_spec.rb +7 -8
- data/spec/help_center/articles_spec.rb +22 -26
- data/spec/help_center/categories_spec.rb +26 -27
- data/spec/help_center/posts_spec.rb +39 -0
- data/spec/help_center/sections_spec.rb +32 -33
- data/spec/help_center/topics_spec.rb +13 -0
- data/spec/lib/paged_collection_spec.rb +11 -11
- data/spec/lib/rate_limit_spec.rb +9 -8
- data/spec/memberships_spec.rb +38 -27
- data/spec/organizations_spec.rb +92 -87
- data/spec/shared/zendesk_resource.rb +40 -25
- data/spec/spec_helper.rb +8 -13
- data/spec/support/client_helper.rb +5 -4
- data/spec/support/data_helper.rb +1 -0
- data/spec/ticket_fields_spec.rb +6 -7
- data/spec/tickets_spec.rb +69 -58
- data/spec/topic_comments_spec.rb +7 -8
- data/spec/topics_spec.rb +5 -6
- data/spec/user_fields_spec.rb +7 -7
- data/spec/user_identities_spec.rb +29 -25
- data/spec/users_spec.rb +88 -78
- data/spec/views_spec.rb +45 -34
- data/spec/zendesk2_spec.rb +3 -2
- data/zendesk2.gemspec +15 -14
- metadata +21 -2
data/lib/zendesk2/model.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Zendesk2::Model
|
2
3
|
include Cistern::Model
|
3
4
|
|
@@ -14,12 +15,12 @@ module Zendesk2::Model
|
|
14
15
|
def save
|
15
16
|
save!
|
16
17
|
rescue Zendesk2::Error => exception
|
17
|
-
self.errors = exception
|
18
|
+
self.errors = error_details(exception)
|
18
19
|
self
|
19
20
|
end
|
20
21
|
|
21
22
|
def destroyed?
|
22
|
-
!
|
23
|
+
!reload
|
23
24
|
end
|
24
25
|
|
25
26
|
def destroy
|
@@ -31,7 +32,7 @@ module Zendesk2::Model
|
|
31
32
|
# re-define Cistern::Attributes#missing_attributes to require non-blank
|
32
33
|
def missing_attributes(args)
|
33
34
|
missing, required = super(args)
|
34
|
-
blank, still_required = required.partition { |_,v|
|
35
|
+
blank, still_required = required.partition { |_, v| '' == v }
|
35
36
|
missing.merge!(Hash[blank])
|
36
37
|
|
37
38
|
[missing, Hash[still_required]]
|
@@ -41,4 +42,14 @@ module Zendesk2::Model
|
|
41
42
|
merge_attributes(attributes)
|
42
43
|
save!
|
43
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def error_details(exception)
|
49
|
+
exception.response[:body]['details'].inject({}) do |a, (k, v)|
|
50
|
+
a.merge(k => v.map { |e| e['type'] || e['description'] })
|
51
|
+
end
|
52
|
+
rescue
|
53
|
+
nil
|
54
|
+
end
|
44
55
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Zendesk2::Organization
|
2
3
|
include Zendesk2::Model
|
3
4
|
|
4
|
-
|
5
5
|
# @return [integer] Automatically assigned when creating organization
|
6
6
|
identity :id, type: :integer # ro[yes] required[no]
|
7
7
|
|
@@ -35,19 +35,19 @@ class Zendesk2::Organization
|
|
35
35
|
def destroy!
|
36
36
|
requires :identity
|
37
37
|
|
38
|
-
cistern.destroy_organization(
|
38
|
+
cistern.destroy_organization('organization' => { 'id' => identity })
|
39
39
|
end
|
40
40
|
|
41
41
|
def save!
|
42
42
|
data = if new_record?
|
43
43
|
requires :name
|
44
44
|
|
45
|
-
cistern.create_organization(
|
45
|
+
cistern.create_organization('organization' => attributes)
|
46
46
|
else
|
47
47
|
requires :identity
|
48
48
|
|
49
|
-
cistern.update_organization(
|
50
|
-
end.body[
|
49
|
+
cistern.update_organization('organization' => attributes)
|
50
|
+
end.body['organization']
|
51
51
|
|
52
52
|
merge_attributes(data)
|
53
53
|
end
|
@@ -57,7 +57,7 @@ class Zendesk2::Organization
|
|
57
57
|
requires :identity
|
58
58
|
|
59
59
|
cistern.users.load(
|
60
|
-
cistern.get_organization_users(
|
60
|
+
cistern.get_organization_users('organization' => { 'id' => identity }).body['users']
|
61
61
|
)
|
62
62
|
end
|
63
63
|
|
@@ -73,7 +73,7 @@ class Zendesk2::Organization
|
|
73
73
|
requires :identity
|
74
74
|
|
75
75
|
cistern.tickets.load(
|
76
|
-
cistern.get_organization_tickets(
|
76
|
+
cistern.get_organization_tickets('organization_id' => identity).body['tickets']
|
77
77
|
)
|
78
78
|
end
|
79
79
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Zendesk2::Organizations
|
2
3
|
include Zendesk2::Collection
|
3
4
|
|
@@ -12,32 +13,33 @@ class Zendesk2::Organizations
|
|
12
13
|
assoc_accessor :user
|
13
14
|
|
14
15
|
def find_by_external_id(external_id)
|
15
|
-
body = cistern.get_organization_by_external_id(
|
16
|
-
|
17
|
-
|
18
|
-
collection.
|
16
|
+
body = cistern.get_organization_by_external_id('external_id' => external_id).body
|
17
|
+
data = body.delete('organizations')
|
18
|
+
if data
|
19
|
+
collection = clone.load(data)
|
20
|
+
collection.merge_attributes(Cistern::Hash.slice(body, 'count', 'next_page', 'previous_page'))
|
19
21
|
collection
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
self.collection_method = :get_organizations
|
24
|
-
self.collection_root =
|
26
|
+
self.collection_root = 'organizations'
|
25
27
|
self.model_method = :get_organization
|
26
|
-
self.model_root =
|
27
|
-
self.search_type =
|
28
|
+
self.model_root = 'organization'
|
29
|
+
self.search_type = 'organization'
|
28
30
|
self.search_request = :search_organization
|
29
31
|
|
30
|
-
def collection_page(params={})
|
31
|
-
collection_method = if
|
32
|
+
def collection_page(params = {})
|
33
|
+
collection_method = if user_id
|
32
34
|
:get_user_organizations
|
33
35
|
else
|
34
36
|
:get_organizations
|
35
37
|
end
|
36
38
|
|
37
|
-
body = cistern.send(collection_method, Cistern::Hash.stringify_keys(
|
39
|
+
body = cistern.send(collection_method, Cistern::Hash.stringify_keys(attributes.merge(params))).body
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
+
load(body[collection_root])
|
42
|
+
merge_attributes(Cistern::Hash.slice(body, 'count', 'next_page', 'previous_page'))
|
41
43
|
self
|
42
44
|
end
|
43
45
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
# adds {#create!} method to {Cistern::Collection}.
|
2
3
|
module Zendesk2::PagedCollection
|
3
4
|
def self.included(klass)
|
4
5
|
klass.send(:attribute, :count)
|
5
|
-
klass.send(:attribute, :next_page_link,
|
6
|
-
klass.send(:attribute, :previous_page_link,
|
6
|
+
klass.send(:attribute, :next_page_link, aliases: 'next_page')
|
7
|
+
klass.send(:attribute, :previous_page_link, aliases: 'previous_page')
|
7
8
|
klass.send(:extend, ClassMethods)
|
8
9
|
end
|
9
10
|
|
11
|
+
# add methods for explicitly defining constants within the collection response
|
10
12
|
module ClassMethods
|
11
13
|
attr_accessor :collection_method, :collection_root, :model_method, :model_root
|
12
14
|
|
@@ -15,14 +17,25 @@ module Zendesk2::PagedCollection
|
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
|
-
def collection_method
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def collection_method
|
21
|
+
self.class.collection_method
|
22
|
+
end
|
23
|
+
|
24
|
+
def collection_root
|
25
|
+
self.class.collection_root
|
26
|
+
end
|
27
|
+
|
28
|
+
def model_method
|
29
|
+
self.class.model_method
|
30
|
+
end
|
31
|
+
|
32
|
+
def model_root
|
33
|
+
self.class.model_root
|
34
|
+
end
|
22
35
|
|
23
36
|
def new_page
|
24
|
-
page = self.class.new(cistern:
|
25
|
-
page.merge_attributes(self.class.scopes.inject({}){|
|
37
|
+
page = self.class.new(cistern: cistern)
|
38
|
+
page.merge_attributes(self.class.scopes.inject({}) { |a, e| a.merge(e.to_s => public_send(e)) })
|
26
39
|
page
|
27
40
|
end
|
28
41
|
|
@@ -44,26 +57,18 @@ module Zendesk2::PagedCollection
|
|
44
57
|
end
|
45
58
|
end
|
46
59
|
|
47
|
-
def all_entries
|
48
|
-
each_entry.to_a
|
49
|
-
end
|
50
|
-
|
51
60
|
def next_page
|
52
61
|
if next_page_link
|
53
|
-
options = {
|
54
|
-
if
|
55
|
-
options.merge!("filtered" => self.filtered)
|
56
|
-
end
|
62
|
+
options = { 'url' => next_page_link }
|
63
|
+
options['filtered'] = filtered if respond_to?(:filtered) # searchable
|
57
64
|
new_page.all(options)
|
58
65
|
end
|
59
66
|
end
|
60
67
|
|
61
68
|
def previous_page
|
62
69
|
if previous_page_link
|
63
|
-
options = {
|
64
|
-
if
|
65
|
-
options.merge!("filtered" => self.filtered)
|
66
|
-
end
|
70
|
+
options = { 'url' => previous_page_link }
|
71
|
+
options['filtered'] = filtered if respond_to?(:filtered) # searchable
|
67
72
|
new_page.all(options)
|
68
73
|
end
|
69
74
|
end
|
@@ -72,8 +77,8 @@ module Zendesk2::PagedCollection
|
|
72
77
|
#
|
73
78
|
# @raise [Zendesk2::Error] if creation was unsuccessful
|
74
79
|
# @return [Zendesk::Model]
|
75
|
-
def create!(attributes={})
|
76
|
-
model =
|
80
|
+
def create!(attributes = {})
|
81
|
+
model = new(Zendesk2.stringify_keys(attributes).merge(Zendesk2.stringify_keys(self.attributes)))
|
77
82
|
model.save!
|
78
83
|
end
|
79
84
|
|
@@ -81,8 +86,8 @@ module Zendesk2::PagedCollection
|
|
81
86
|
#
|
82
87
|
# @see {#create!} to raise an exception on failure
|
83
88
|
# @return [Zendesk::Model, FalseClass]
|
84
|
-
def create(attributes={})
|
85
|
-
model =
|
89
|
+
def create(attributes = {})
|
90
|
+
model = new(attributes.merge(Zendesk2.stringify_keys(self.attributes)))
|
86
91
|
model.save
|
87
92
|
end
|
88
93
|
|
@@ -94,7 +99,7 @@ module Zendesk2::PagedCollection
|
|
94
99
|
end
|
95
100
|
|
96
101
|
# Fetch a collection of resources
|
97
|
-
def all(params={})
|
102
|
+
def all(params = {})
|
98
103
|
if search_query?(params)
|
99
104
|
search_page(params)
|
100
105
|
else
|
@@ -119,19 +124,18 @@ module Zendesk2::PagedCollection
|
|
119
124
|
# @raise [Zendesk2::Error] if the record cannot be found or other request error
|
120
125
|
# @return [Zendesk2::Model] fetched resource corresponding to value of {Zendesk2::Collection#model}
|
121
126
|
def get!(identity_or_hash)
|
122
|
-
scoped_attributes = self.class.scopes.inject({}){|
|
127
|
+
scoped_attributes = self.class.scopes.inject({}) { |a, e| a.merge(e.to_s => send(e)) }
|
123
128
|
|
124
129
|
if identity_or_hash.is_a?(Hash)
|
125
130
|
scoped_attributes.merge!(identity_or_hash)
|
126
131
|
else
|
127
|
-
scoped_attributes
|
132
|
+
scoped_attributes['id'] = identity_or_hash
|
128
133
|
end
|
129
134
|
|
130
135
|
scoped_attributes = { model_root => scoped_attributes }
|
131
136
|
|
132
|
-
|
133
|
-
|
134
|
-
end
|
137
|
+
data = cistern.send(model_method, scoped_attributes).body[model_root]
|
138
|
+
new(data) if data
|
135
139
|
end
|
136
140
|
|
137
141
|
# Quiet version of {#get!}
|
@@ -148,20 +152,20 @@ module Zendesk2::PagedCollection
|
|
148
152
|
protected
|
149
153
|
|
150
154
|
def search_query?(params)
|
151
|
-
|
155
|
+
params['filtered'] && params['url']
|
152
156
|
end
|
153
157
|
|
154
158
|
def search_page(params)
|
155
|
-
query = Faraday::NestedParamsEncoder.decode(URI.parse(params.fetch(
|
159
|
+
query = Faraday::NestedParamsEncoder.decode(URI.parse(params.fetch('url')).query)
|
156
160
|
|
157
|
-
search(query.delete(
|
161
|
+
search(query.delete('query'), query)
|
158
162
|
end
|
159
163
|
|
160
164
|
def collection_page(params)
|
161
|
-
scoped_attributes = self.class.scopes.inject({}) { |
|
165
|
+
scoped_attributes = self.class.scopes.inject({}) { |a, e| a.merge(e.to_s => send(e)) }.merge(params)
|
162
166
|
body = cistern.send(collection_method, scoped_attributes).body
|
163
167
|
|
164
|
-
|
165
|
-
|
168
|
+
load(body[collection_root]) # 'results' is the key for paged seraches
|
169
|
+
merge_attributes(Cistern::Hash.slice(body, 'count', 'next_page', 'previous_page'))
|
166
170
|
end
|
167
171
|
end
|
data/lib/zendesk2/rate_limit.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'logger'
|
2
3
|
|
4
|
+
# Faraday middleware to block and sleep on rate limit events
|
3
5
|
class Zendesk2::RateLimit
|
4
|
-
|
5
6
|
attr_reader :logger
|
6
7
|
|
7
|
-
def initialize(app, options={})
|
8
|
+
def initialize(app, options = {})
|
8
9
|
@app = app
|
9
10
|
@logger = options[:logger] || ::Logger.new(nil)
|
10
11
|
end
|
data/lib/zendesk2/real.rb
CHANGED
@@ -1,29 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Zendesk2::Real
|
2
|
-
|
3
3
|
attr_accessor :username, :url, :token, :logger, :jwt_token, :last_request
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
6
|
+
def initialize(options = {})
|
7
|
+
url = options[:url] || Zendesk2.defaults[:url]
|
8
|
+
|
9
|
+
@url = (URI.parse(url).to_s if url)
|
9
10
|
|
10
11
|
@logger = options[:logger] || Logger.new(nil)
|
11
|
-
adapter
|
12
|
+
@adapter = options[:adapter] || Faraday.default_adapter
|
12
13
|
@username = options[:username] || Zendesk2.defaults[:username]
|
13
14
|
@token = options.fetch(:token, Zendesk2.defaults[:token])
|
14
15
|
password = options[:password] || Zendesk2.defaults[:password]
|
15
16
|
|
16
|
-
cistern_options = options[:cistern_options] || {}
|
17
|
-
|
18
17
|
@auth_token = password || @token
|
19
18
|
@auth_id = "#{@username}/token" if @auth_token == @token
|
20
19
|
@jwt_token = options[:jwt_token]
|
21
20
|
|
22
|
-
raise
|
23
|
-
raise
|
24
|
-
raise
|
21
|
+
raise 'Missing required options: :url' unless @url
|
22
|
+
raise 'Missing required options: :username' unless @auth_id
|
23
|
+
raise 'Missing required options: :password or :token' unless password || @token
|
24
|
+
|
25
|
+
connection
|
26
|
+
end
|
25
27
|
|
26
|
-
|
28
|
+
def connection
|
29
|
+
@connection ||= Faraday.new(url: @url) do |connection|
|
27
30
|
# response
|
28
31
|
connection.use Faraday::Request::BasicAuthentication, @auth_id, @auth_token
|
29
32
|
connection.use Faraday::Response::RaiseError
|
@@ -35,27 +38,27 @@ class Zendesk2::Real
|
|
35
38
|
|
36
39
|
# idempotency
|
37
40
|
connection.request :retry,
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
max: 30,
|
42
|
+
interval: 1,
|
43
|
+
interval_randomness: 0.2,
|
44
|
+
backoff_factor: 2
|
42
45
|
|
43
46
|
# rate limit
|
44
47
|
connection.use Zendesk2::RateLimit, logger: @logger
|
45
48
|
|
46
49
|
connection.use Zendesk2::Logger, @logger
|
47
|
-
connection.adapter(
|
50
|
+
connection.adapter(*@adapter)
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
51
|
-
def request(options={})
|
54
|
+
def request(options = {})
|
52
55
|
method = options[:method] || :get
|
53
|
-
url = options[:url] || File.join(@url,
|
56
|
+
url = options[:url] || File.join(@url, '/api/v2', options[:path])
|
54
57
|
params = options[:params] || {}
|
55
58
|
body = options[:body]
|
56
|
-
headers = {
|
59
|
+
headers = { 'User-Agent' => Zendesk2::USER_AGENT }.merge(options[:headers] || {})
|
57
60
|
|
58
|
-
|
61
|
+
connection.send(method) do |req|
|
59
62
|
req.url(url)
|
60
63
|
req.headers.merge!(headers)
|
61
64
|
req.params.merge!(params)
|
@@ -64,6 +67,6 @@ class Zendesk2::Real
|
|
64
67
|
rescue Faraday::ConnectionFailed
|
65
68
|
raise
|
66
69
|
rescue Faraday::Error::ClientError => e
|
67
|
-
raise Zendesk2::Error
|
70
|
+
raise Zendesk2::Error, e
|
68
71
|
end
|
69
72
|
end
|
data/lib/zendesk2/request.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Zendesk2::Request
|
2
|
-
|
3
3
|
class << self
|
4
4
|
alias cistern_included included
|
5
5
|
|
@@ -10,8 +10,9 @@ module Zendesk2::Request
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
# provide class-level request information
|
13
14
|
module ClassMethods
|
14
|
-
def request_method(request_method=nil)
|
15
|
+
def request_method(request_method = nil)
|
15
16
|
@request_method ||= request_method
|
16
17
|
end
|
17
18
|
|
@@ -36,15 +37,15 @@ module Zendesk2::Request
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def error_map
|
39
|
-
|
40
|
-
:
|
41
|
-
|
42
|
-
|
43
|
-
}],
|
44
|
-
:
|
45
|
-
|
46
|
-
|
47
|
-
}],
|
40
|
+
@error_map ||= {
|
41
|
+
invalid: [422, {
|
42
|
+
'error' => 'RecordInvalid',
|
43
|
+
'description' => 'Record validation errors',
|
44
|
+
},],
|
45
|
+
not_found: [404, {
|
46
|
+
'error' => 'RecordNotFound',
|
47
|
+
'description' => 'Not found',
|
48
|
+
},],
|
48
49
|
}
|
49
50
|
end
|
50
51
|
end
|
@@ -55,23 +56,25 @@ module Zendesk2::Request
|
|
55
56
|
@params = Cistern::Hash.stringify_keys(params)
|
56
57
|
end
|
57
58
|
|
58
|
-
def _mock(params={})
|
59
|
+
def _mock(params = {})
|
59
60
|
setup(params)
|
60
61
|
mock
|
61
62
|
end
|
62
63
|
|
63
|
-
def _real(params={})
|
64
|
+
def _real(params = {})
|
64
65
|
setup(params)
|
65
66
|
real
|
66
67
|
end
|
67
68
|
|
68
69
|
def page_params!(options)
|
69
|
-
|
70
|
+
url = options.delete('url')
|
71
|
+
|
72
|
+
page_params = if url
|
70
73
|
Faraday::NestedParamsEncoder.decode(URI.parse(url).query)
|
71
74
|
else
|
72
75
|
Cistern::Hash.stringify_keys(options)
|
73
76
|
end
|
74
|
-
Cistern::Hash.slice(page_params,
|
77
|
+
Cistern::Hash.slice(page_params, 'per_page', 'page', 'query')
|
75
78
|
end
|
76
79
|
|
77
80
|
def page_params?
|
@@ -79,9 +82,7 @@ module Zendesk2::Request
|
|
79
82
|
end
|
80
83
|
|
81
84
|
def request_params
|
82
|
-
page_params = if page_params?
|
83
|
-
page_params!(self.params)
|
84
|
-
end
|
85
|
+
page_params = (page_params!(params) if page_params?)
|
85
86
|
|
86
87
|
if self.class.request_params
|
87
88
|
self.class.request_params.call(self)
|
@@ -94,7 +95,7 @@ module Zendesk2::Request
|
|
94
95
|
case (generator = self.class.request_path)
|
95
96
|
when Proc then
|
96
97
|
generator.call(self)
|
97
|
-
else raise ArgumentError
|
98
|
+
else raise ArgumentError, "Couldn't generate request_path from #{generator.inspect}"
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
@@ -109,97 +110,92 @@ module Zendesk2::Request
|
|
109
110
|
|
110
111
|
def pluralize(word)
|
111
112
|
pluralized = word.dup
|
112
|
-
[[/y$/, 'ies'], [/$/, 's']].find{|regex, replace| pluralized.gsub!(regex, replace) if pluralized.match(regex)}
|
113
|
+
[[/y$/, 'ies'], [/$/, 's']].find { |regex, replace| pluralized.gsub!(regex, replace) if pluralized.match(regex) }
|
113
114
|
pluralized
|
114
115
|
end
|
115
116
|
|
116
117
|
def data
|
117
|
-
|
118
|
+
cistern.data
|
118
119
|
end
|
119
120
|
|
120
121
|
def html_url_for(path)
|
121
122
|
File.join(cistern.url, path.to_s)
|
122
123
|
end
|
123
124
|
|
124
|
-
def url_for(path, options={})
|
125
|
+
def url_for(path, options = {})
|
125
126
|
URI.parse(
|
126
|
-
File.join(cistern.url,
|
127
|
+
File.join(cistern.url, '/api/v2', path.to_s),
|
127
128
|
).tap do |uri|
|
128
|
-
|
129
|
-
|
130
|
-
end
|
129
|
+
query = options[:query]
|
130
|
+
query && (uri.query = Faraday::NestedParamsEncoder.encode(query))
|
131
131
|
end.to_s
|
132
132
|
end
|
133
133
|
|
134
|
-
def real(params={})
|
135
|
-
cistern.request(:
|
136
|
-
:
|
137
|
-
:
|
138
|
-
:
|
139
|
-
:
|
140
|
-
)
|
134
|
+
def real(params = {})
|
135
|
+
cistern.request(method: self.class.request_method,
|
136
|
+
path: request_path,
|
137
|
+
body: request_body,
|
138
|
+
url: params['url'],
|
139
|
+
params: request_params,)
|
141
140
|
end
|
142
141
|
|
143
|
-
def real_request(params={})
|
142
|
+
def real_request(params = {})
|
144
143
|
request({
|
145
|
-
:
|
146
|
-
:
|
147
|
-
:
|
148
|
-
}.merge(cistern
|
144
|
+
method: self.class.request_method,
|
145
|
+
path: request_path(params),
|
146
|
+
body: request_body(params),
|
147
|
+
}.merge(cistern.hash.slice(params, :method, :path, :body, :headers),),)
|
149
148
|
end
|
150
149
|
|
151
|
-
def mock_response(body, options={})
|
150
|
+
def mock_response(body, options = {})
|
152
151
|
response(
|
153
|
-
:
|
154
|
-
:
|
155
|
-
:
|
156
|
-
:
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
152
|
+
method: self.class.request_method,
|
153
|
+
path: options[:path] || request_path,
|
154
|
+
request_body: request_body,
|
155
|
+
response_body: body,
|
156
|
+
headers: options[:headers] || {},
|
157
|
+
status: options[:status] || 200,
|
158
|
+
params: options[:params] || request_params,
|
160
159
|
)
|
161
160
|
end
|
162
161
|
|
163
|
-
def find!(collection, identity, options={})
|
164
|
-
|
165
|
-
|
166
|
-
else
|
167
|
-
error!(options[:error] || :not_found, options)
|
168
|
-
end
|
162
|
+
def find!(collection, identity, options = {})
|
163
|
+
resource = cistern.data[collection][identity.to_i]
|
164
|
+
resource || error!(options[:error] || :not_found, options)
|
169
165
|
end
|
170
166
|
|
171
|
-
def delete!(collection, identity, options={})
|
172
|
-
|
167
|
+
def delete!(collection, identity, options = {})
|
168
|
+
cistern.data[collection].delete(identity.to_i) ||
|
173
169
|
error!(options[:error] || :not_found, options)
|
174
170
|
end
|
175
171
|
|
176
|
-
def error!(type, options={})
|
172
|
+
def error!(type, options = {})
|
177
173
|
status, body = self.class.error_map[type]
|
178
|
-
body
|
174
|
+
body['details'] = options[:details] if options[:details]
|
179
175
|
|
180
176
|
response(
|
181
|
-
:
|
182
|
-
:
|
183
|
-
:
|
177
|
+
path: request_path,
|
178
|
+
status: status,
|
179
|
+
body: body,
|
184
180
|
)
|
185
181
|
end
|
186
182
|
|
187
|
-
def resources(collection, options={})
|
183
|
+
def resources(collection, options = {})
|
188
184
|
page = collection.is_a?(Array) ? collection : cistern.data[collection.to_sym].values
|
189
185
|
root = options.fetch(:root) { !collection.is_a?(Array) && collection.to_s }
|
190
186
|
|
191
187
|
mock_response(
|
192
188
|
root => page,
|
193
|
-
|
189
|
+
'count' => page.size,
|
194
190
|
)
|
195
191
|
end
|
196
192
|
|
197
|
-
def page(collection, options={})
|
193
|
+
def page(collection, options = {})
|
198
194
|
url_params = options[:params] || params
|
199
195
|
page_params = page_params!(params)
|
200
196
|
|
201
|
-
page_size = (page_params.delete(
|
202
|
-
page_index = (page_params.delete(
|
197
|
+
page_size = (page_params.delete('per_page') || 50).to_i
|
198
|
+
page_index = (page_params.delete('page') || 1).to_i
|
203
199
|
root = options.fetch(:root) { !collection.is_a?(Array) && collection.to_s }
|
204
200
|
path = options[:path] || request_path
|
205
201
|
|
@@ -210,24 +206,24 @@ module Zendesk2::Request
|
|
210
206
|
total_pages = (count / page_size) + 1
|
211
207
|
|
212
208
|
next_page = if page_index < total_pages
|
213
|
-
url_for(path, query: {
|
209
|
+
url_for(path, query: { 'page' => page_index + 1, 'per_page' => page_size }.merge(url_params))
|
214
210
|
end
|
215
211
|
previous_page = if page_index > 1
|
216
|
-
url_for(path, query: {
|
212
|
+
url_for(path, query: { 'page' => page_index - 1, 'per_page' => page_size }.merge(url_params))
|
217
213
|
end
|
218
214
|
|
219
215
|
resource_page = resources.slice(offset, page_size)
|
220
216
|
|
221
217
|
body = {
|
222
218
|
root => resource_page,
|
223
|
-
|
224
|
-
|
225
|
-
|
219
|
+
'count' => count,
|
220
|
+
'next_page' => next_page,
|
221
|
+
'previous_page' => previous_page,
|
226
222
|
}
|
227
223
|
|
228
224
|
response(
|
229
|
-
:
|
230
|
-
:
|
225
|
+
body: body,
|
226
|
+
path: path,
|
231
227
|
)
|
232
228
|
end
|
233
229
|
|
@@ -245,18 +241,18 @@ module Zendesk2::Request
|
|
245
241
|
# \@request_body is special because it's need for spec assertions but
|
246
242
|
# {Faraday::Env} replaces the request body with the response body after
|
247
243
|
# the request and the reference is lost
|
248
|
-
def response(options={})
|
244
|
+
def response(options = {})
|
249
245
|
body = options[:response_body] || options[:body]
|
250
246
|
method = options[:method] || :get
|
251
247
|
params = options[:params]
|
252
248
|
cistern.last_request = options[:request_body]
|
253
|
-
status = options[:status]
|
249
|
+
status = options[:status] || 200
|
254
250
|
|
255
251
|
path = options[:path]
|
256
252
|
url = options[:url] || url_for(path, query: params)
|
257
253
|
|
258
|
-
request_headers = {
|
259
|
-
response_headers = {
|
254
|
+
request_headers = { 'Accept' => 'application/json' }
|
255
|
+
response_headers = { 'Content-Type' => 'application/json; charset=utf-8' }
|
260
256
|
|
261
257
|
# request phase
|
262
258
|
# * :method - :get, :post, ...
|
@@ -269,17 +265,17 @@ module Zendesk2::Request
|
|
269
265
|
# * :body - the response body
|
270
266
|
# * :response_headers
|
271
267
|
env = Faraday::Env.from(
|
272
|
-
:
|
273
|
-
:
|
274
|
-
:
|
275
|
-
:
|
276
|
-
:
|
277
|
-
:
|
268
|
+
method: method,
|
269
|
+
url: URI.parse(url),
|
270
|
+
body: body,
|
271
|
+
request_headers: request_headers,
|
272
|
+
response_headers: response_headers,
|
273
|
+
status: status,
|
278
274
|
)
|
279
275
|
|
280
276
|
Faraday::Response::RaiseError.new.on_complete(env) ||
|
281
277
|
Faraday::Response.new(env)
|
282
278
|
rescue Faraday::Error::ClientError => e
|
283
|
-
raise Zendesk2::Error
|
279
|
+
raise Zendesk2::Error, e
|
284
280
|
end
|
285
281
|
end
|