desk_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +5 -0
  5. data/.yardopts +3 -0
  6. data/Gemfile +15 -0
  7. data/Guardfile +5 -0
  8. data/LICENSE +7 -0
  9. data/README.md +185 -0
  10. data/Rakefile +15 -0
  11. data/config.rb +7 -0
  12. data/desk_api.gemspec +36 -0
  13. data/lib/desk/action/create.rb +15 -0
  14. data/lib/desk/action/delete.rb +9 -0
  15. data/lib/desk/action/embedded.rb +12 -0
  16. data/lib/desk/action/field.rb +33 -0
  17. data/lib/desk/action/link.rb +29 -0
  18. data/lib/desk/action/resource.rb +14 -0
  19. data/lib/desk/action/search.rb +15 -0
  20. data/lib/desk/action/update.rb +12 -0
  21. data/lib/desk/client.rb +67 -0
  22. data/lib/desk/configuration.rb +132 -0
  23. data/lib/desk/default.rb +67 -0
  24. data/lib/desk/error/bad_gateway.rb +10 -0
  25. data/lib/desk/error/bad_request.rb +10 -0
  26. data/lib/desk/error/client_error.rb +9 -0
  27. data/lib/desk/error/configuration_error.rb +8 -0
  28. data/lib/desk/error/conflict.rb +10 -0
  29. data/lib/desk/error/forbidden.rb +10 -0
  30. data/lib/desk/error/gateway_timeout.rb +10 -0
  31. data/lib/desk/error/internal_server_error.rb +10 -0
  32. data/lib/desk/error/method_not_allowed.rb +10 -0
  33. data/lib/desk/error/method_not_supported.rb +9 -0
  34. data/lib/desk/error/not_acceptable.rb +10 -0
  35. data/lib/desk/error/not_found.rb +10 -0
  36. data/lib/desk/error/parse_error.rb +9 -0
  37. data/lib/desk/error/parser_error.rb +9 -0
  38. data/lib/desk/error/server_error.rb +9 -0
  39. data/lib/desk/error/service_unavailable.rb +10 -0
  40. data/lib/desk/error/too_many_requests.rb +10 -0
  41. data/lib/desk/error/unauthorized.rb +10 -0
  42. data/lib/desk/error/unprocessable_entity.rb +10 -0
  43. data/lib/desk/error/unsupported_media_type.rb +10 -0
  44. data/lib/desk/error.rb +61 -0
  45. data/lib/desk/rate_limit.rb +26 -0
  46. data/lib/desk/request/retry.rb +51 -0
  47. data/lib/desk/resource/article.rb +10 -0
  48. data/lib/desk/resource/article_translation.rb +8 -0
  49. data/lib/desk/resource/attachment.rb +8 -0
  50. data/lib/desk/resource/case.rb +9 -0
  51. data/lib/desk/resource/company.rb +8 -0
  52. data/lib/desk/resource/customer.rb +9 -0
  53. data/lib/desk/resource/integration_url.rb +9 -0
  54. data/lib/desk/resource/job.rb +7 -0
  55. data/lib/desk/resource/label.rb +9 -0
  56. data/lib/desk/resource/macro.rb +9 -0
  57. data/lib/desk/resource/macro_action.rb +7 -0
  58. data/lib/desk/resource/note.rb +7 -0
  59. data/lib/desk/resource/page.rb +81 -0
  60. data/lib/desk/resource/reply.rb +8 -0
  61. data/lib/desk/resource/topic.rb +9 -0
  62. data/lib/desk/resource/topic_translation.rb +9 -0
  63. data/lib/desk/resource/user_preference.rb +7 -0
  64. data/lib/desk/resource.rb +53 -0
  65. data/lib/desk/resources.json +76 -0
  66. data/lib/desk/response/raise_error.rb +34 -0
  67. data/lib/desk/version.rb +3 -0
  68. data/lib/desk.rb +35 -0
  69. data/spec/cassettes/Desk_Client/_delete/deletes_a_resource.yml +48 -0
  70. data/spec/cassettes/Desk_Client/_get/fetches_resources.yml +55 -0
  71. data/spec/cassettes/Desk_Client/_patch/updates_a_resource.yml +62 -0
  72. data/spec/cassettes/Desk_Client/_post/creates_a_resource.yml +58 -0
  73. data/spec/cassettes/Desk_Error/_from_response/can_be_created_from_a_faraday_response.yml +54 -0
  74. data/spec/cassettes/Desk_Error/_from_response/uses_the_body_message_if_present.yml +54 -0
  75. data/spec/cassettes/Desk_Resource/_by_url/finds_resources_by_url.yml +313 -0
  76. data/spec/cassettes/Desk_Resource/_create/creates_a_new_topic.yml +58 -0
  77. data/spec/cassettes/Desk_Resource/_delete/deletes_a_resource.yml +164 -0
  78. data/spec/cassettes/Desk_Resource/_delete/throws_an_error_deleting_a_non_deletalbe_resource.yml +56 -0
  79. data/spec/cassettes/Desk_Resource/_exec_/can_be_forced_to_reload.yml +313 -0
  80. data/spec/cassettes/Desk_Resource/_exec_/loads_the_current_resource.yml +313 -0
  81. data/spec/cassettes/Desk_Resource/_method_missing/loads_the_resource_to_find_a_suitable_method.yml +313 -0
  82. data/spec/cassettes/Desk_Resource/_method_missing/raises_an_error_if_method_does_not_exist.yml +313 -0
  83. data/spec/cassettes/Desk_Resource/_search/allows_searching_on_search_enabled_resources.yml +54 -0
  84. data/spec/cassettes/Desk_Resource/_update/throws_an_error_updating_a_user.yml +56 -0
  85. data/spec/cassettes/Desk_Resource/_update/updates_a_topic.yml +118 -0
  86. data/spec/cassettes/Desk_Resource_Page/_by_id/loads_the_requested_resource.yml +54 -0
  87. data/spec/cassettes/Desk_Resource_Page/_page/keeps_the_resource_as_loaded.yml +113 -0
  88. data/spec/cassettes/Desk_Resource_Page/_page/returns_the_current_page_and_loads_if_page_not_defined.yml +313 -0
  89. data/spec/cassettes/Desk_Resource_Page/_page/sets_the_resource_to_not_loaded.yml +113 -0
  90. data/spec/desk/client_spec.rb +133 -0
  91. data/spec/desk/configuration_spec.rb +183 -0
  92. data/spec/desk/default_spec.rb +69 -0
  93. data/spec/desk/error_spec.rb +23 -0
  94. data/spec/desk/rate_limit_spec.rb +42 -0
  95. data/spec/desk/request/retry_spec.rb +46 -0
  96. data/spec/desk/resource_spec.rb +119 -0
  97. data/spec/desk/resources/page_spec.rb +64 -0
  98. data/spec/desk_spec.rb +43 -0
  99. data/spec/spec_helper.rb +39 -0
  100. metadata +347 -0
@@ -0,0 +1,67 @@
1
+ require 'desk/version'
2
+
3
+ module Desk
4
+ module Default
5
+ CONNECTION_OPTIONS = {
6
+ headers: {
7
+ accept: 'application/json',
8
+ user_agent: "desk.com Ruby Gem v#{Desk::VERSION}"
9
+ },
10
+ request: {
11
+ open_timeout: 5,
12
+ timeout: 10
13
+ }
14
+ } unless defined? Desk::Default::CONNECTION_OPTIONS
15
+
16
+ class << self
17
+ # @return [Hash]
18
+ def options
19
+ Hash[Desk::Configuration.keys.map{|key| [key, send(key)]}]
20
+ end
21
+
22
+ # @return [String]
23
+ def username
24
+ ENV['DESK_USERNAME']
25
+ end
26
+
27
+ # @return [String]
28
+ def password
29
+ ENV['DESK_PASSWORD']
30
+ end
31
+
32
+ # @return [String]
33
+ def consumer_key
34
+ ENV['DESK_CONSUMER_KEY']
35
+ end
36
+
37
+ # @return [String]
38
+ def consumer_secret
39
+ ENV['DESK_CONSUMER_SECRET']
40
+ end
41
+
42
+ # @return [String]
43
+ def token
44
+ ENV['DESK_TOKEN']
45
+ end
46
+
47
+ # @return [String]
48
+ def token_secret
49
+ ENV['DESK_TOKEN_SECRET']
50
+ end
51
+
52
+ # @return [String]
53
+ def subdomain
54
+ ENV['DESK_SUBDOMAIN']
55
+ end
56
+
57
+ # @return [String]
58
+ def endpoint
59
+ ENV['DESK_ENDPOINT']
60
+ end
61
+
62
+ def connection_options
63
+ CONNECTION_OPTIONS
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/server_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when Desk returns the HTTP status code 502
6
+ class BadGateway < Desk::Error::ServerError
7
+ HTTP_STATUS_CODE = 502
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 400
6
+ class BadRequest < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 400
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns a 4xx HTTP status code or there's an error in Faraday
6
+ class ClientError < Desk::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ class ConfigurationError < ::ArgumentError
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 409
6
+ class Conflict < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 409
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 403
6
+ class Forbidden < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 403
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/server_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when Desk returns the HTTP status code 504
6
+ class GatewayTimeout < Desk::Error::ServerError
7
+ HTTP_STATUS_CODE = 504
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/server_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when Desk returns the HTTP status code 500
6
+ class InternalServerError < Desk::Error::ServerError
7
+ HTTP_STATUS_CODE = 500
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 405
6
+ class MethodNotAllowed < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 405
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when trying to search a resource that doesn't support search
6
+ class MethodNotSupported < Desk::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 406
6
+ class NotAcceptable < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 406
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 404
6
+ class NotFound < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 404
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when JSON parsing fails
6
+ class ParserError < Desk::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when JSON parsing fails
6
+ class ParserError < Desk::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'desk/error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when Desk returns a 5xx HTTP status code
6
+ class ServerError < Desk::Error
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/server_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when Desk returns the HTTP status code 503
6
+ class ServiceUnavailable < Desk::Error::ServerError
7
+ HTTP_STATUS_CODE = 503
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 429
6
+ class TooManyRequests < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 429
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 401
6
+ class Unauthorized < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 401
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 422
6
+ class UnprocessableEntity < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 422
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ require 'desk/error/client_error'
2
+
3
+ module Desk
4
+ class Error
5
+ # Raised when desk.com returns the HTTP status code 415
6
+ class UnsupportedMediaType < Desk::Error::ClientError
7
+ HTTP_STATUS_CODE = 415
8
+ end
9
+ end
10
+ end
data/lib/desk/error.rb ADDED
@@ -0,0 +1,61 @@
1
+ require 'desk/rate_limit'
2
+
3
+ module Desk
4
+ # Custom error class for rescuing from all desk.com errors
5
+ class Error < StandardError
6
+ attr_reader :rate_limit
7
+
8
+ # Initializes a new Error object
9
+ #
10
+ # @param exception [Exception, String]
11
+ # @param response_headers [Hash]
12
+ # @param code [Integer]
13
+ # @return [Desk::Error]
14
+ def initialize(exception=$!, response_headers={}, code = nil)
15
+ @rate_limit = Desk::RateLimit.new(response_headers)
16
+ @wrapped_exception = exception
17
+ @code = code
18
+ exception.respond_to?(:backtrace) ? super(exception.message) : super(exception.to_s)
19
+ end
20
+
21
+ def backtrace
22
+ @wrapped_exception.respond_to?(:backtrace) ? @wrapped_exception.backtrace : super
23
+ end
24
+
25
+ class << self
26
+ # Create a new error from an HTTP response
27
+ #
28
+ # @param response [Hash]
29
+ # @return [Desk::Error]
30
+ def from_response(response = {})
31
+ error, code = parse_error(response[:body]), response[:status]
32
+ new(error, response[:response_headers], code)
33
+ end
34
+
35
+ # @return [Hash]
36
+ def errors
37
+ @errors ||= descendants.each_with_object({}) do |klass, hash|
38
+ hash[klass::HTTP_STATUS_CODE] = klass
39
+ end
40
+ end
41
+
42
+ # @return [Array]
43
+ def descendants
44
+ @descendants ||= []
45
+ end
46
+
47
+ # @return [Array]
48
+ def inherited(descendant)
49
+ descendants << descendant
50
+ end
51
+
52
+ private
53
+
54
+ def parse_error(body)
55
+ if body['message']
56
+ body['message']
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,26 @@
1
+ module Desk
2
+ class RateLimit
3
+ def initialize(attrs = {})
4
+ @attrs = attrs
5
+ end
6
+
7
+ # @return [Integer]
8
+ def limit
9
+ limit = @attrs['x-rate-limit-limit']
10
+ limit.to_i if limit
11
+ end
12
+
13
+ # @return [Integer]
14
+ def remaining
15
+ remaining = @attrs['x-rate-limit-remaining']
16
+ remaining.to_i if remaining
17
+ end
18
+
19
+ # @return [Integer]
20
+ def reset_in
21
+ reset_in = @attrs['x-rate-limit-reset']
22
+ reset_in.to_i if reset_in
23
+ end
24
+ alias retry_after reset_in
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ module Desk
2
+ module Request
3
+ class Retry < Faraday::Request::Retry
4
+ def initialize(app, options = {})
5
+ @max = options[:max] || 3
6
+ @interval = options[:interval] || 10
7
+ super(app)
8
+ end
9
+
10
+ def call(env)
11
+ retries = @retries
12
+ interval = @interval
13
+
14
+ begin
15
+ @app.call(env)
16
+ rescue Desk::Error::TooManyRequests => e
17
+ if retries > 0 and e.rate_limit.reset_in
18
+ retries = 0
19
+ sleep e.rate_limit.reset_in
20
+ retry
21
+ end
22
+ raise
23
+ rescue exception_matcher
24
+ if retries > 0
25
+ retries -= 1
26
+ sleep @interval
27
+ retry
28
+ end
29
+ raise
30
+ end
31
+ end
32
+
33
+ def exception_matcher
34
+ exceptions = [Errno::ETIMEDOUT, 'Timeout::Error', Faraday::Error::TimeoutError]
35
+ matcher = Module.new
36
+ (class << matcher; self; end).class_eval do
37
+ define_method(:===) do |error|
38
+ exceptions.any? do |ex|
39
+ if ex.is_a? Module then error.is_a? ex
40
+ else error.class.to_s == ex.to_s
41
+ end
42
+ end
43
+ end
44
+ end
45
+ matcher
46
+ end
47
+ end
48
+
49
+ Faraday.register_middleware :request, retry: lambda { Retry }
50
+ end
51
+ end
@@ -0,0 +1,10 @@
1
+ module Desk
2
+ class Resource
3
+ class Article < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ include Desk::Action::Search
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Desk
2
+ class Resource
3
+ class ArticleTranslation < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Desk
2
+ class Resource
3
+ class Attachment < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Delete
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class Case < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Search
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Desk
2
+ class Resource
3
+ class Company < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class Customer < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Search
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class IntegrationUrl < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Desk
2
+ class Resource
3
+ class Job < Desk::Resource
4
+ include Desk::Action::Create
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class Article < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class Macro < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Desk
2
+ class Resource
3
+ class MacroAction < Desk::Resource
4
+ include Desk::Action::Update
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Desk
2
+ class Resource
3
+ class Note < Desk::Resource
4
+ include Desk::Action::Create
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,81 @@
1
+ module Desk
2
+ class Resource
3
+ class Page < Desk::Resource
4
+ include Enumerable
5
+ include Desk::Action::Embedded
6
+
7
+ [
8
+ :all?, :any?,
9
+ :collect, :each, :entries, :find, :find_all,
10
+ :find_index, :first, :first, :group_by, :last,
11
+ :map, :map!, :none?, :one?, :partition, :reduce,
12
+ :reject, :select, :sort, :sort_by, :taken, :zip
13
+ ].each do |method|
14
+ define_method(method) do |*args, &block|
15
+ exec!.records.send(method, *args, &block)
16
+ end
17
+ end
18
+
19
+ def search(params)
20
+ raise Desk::Error::MethodNotSupported unless base_class.respond_to?(:search)
21
+ url = Addressable::URI.parse(clean_base_url + '/search')
22
+ url.query_values = params
23
+ base_class.search(client, url.to_s).exec!
24
+ end
25
+
26
+ def create(params)
27
+ raise Desk::Error::MethodNotSupported unless base_class.respond_to?(:create)
28
+ base_class.create(client, clean_base_url, params)
29
+ end
30
+
31
+ [:page, :per_page].each do |method|
32
+ define_method(method) do |value = nil|
33
+ if not value
34
+ self.exec! if self.query_params(method.to_s) == nil
35
+ return self.query_params(method.to_s).to_i
36
+ end
37
+ self.query_params = Hash[method.to_s, value.to_s]
38
+ self
39
+ end
40
+ end
41
+
42
+ def by_id(id)
43
+ by_url("#{clean_base_url}/#{id}")
44
+ end
45
+
46
+ protected
47
+
48
+ attr_reader :records
49
+
50
+ def setup(definition)
51
+ setup_embedded(definition._embedded['entries']) if definition._embedded?
52
+ super(definition)
53
+ end
54
+
55
+ def query_params(param)
56
+ params = Addressable::URI.parse(@_links.self.href).query_values || {}
57
+ params.include?(param) ? params[param] : nil
58
+ end
59
+
60
+ def query_params=(params = {})
61
+ return @_links.self.href if params.empty?
62
+
63
+ uri = Addressable::URI.parse(@_links.self.href)
64
+ params = (uri.query_values || {}).merge(params)
65
+
66
+ @loaded = false unless params == uri.query_values
67
+
68
+ uri.query_values = params
69
+ @_links.self.href = uri.to_s
70
+ end
71
+
72
+ def clean_base_url
73
+ Addressable::URI.parse(@_links.self.href).path.gsub(/\/search$/, '')
74
+ end
75
+
76
+ def base_class
77
+ resource(clean_base_url[/\w+$/].singularize)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,8 @@
1
+ module Desk
2
+ class Resource
3
+ class Reply < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class Topic < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Desk
2
+ class Resource
3
+ class TopicTranslation < Desk::Resource
4
+ include Desk::Action::Create
5
+ include Desk::Action::Update
6
+ include Desk::Action::Delete
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Desk
2
+ class Resource
3
+ class UserPreference < Desk::Resource
4
+ include Desk::Action::Update
5
+ end
6
+ end
7
+ end