freshdesk_api 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cba704113b86c43fdeab78e8cd4361dc661d1092
4
+ data.tar.gz: e839a871d07cd30b70810f1b072f1dce280bf7ea
5
+ SHA512:
6
+ metadata.gz: dcb1084b51ccacb63daf5ea6389e2f950c0b054b1e68dd32cb9ce035a9d15f67e986b957401abc0131dde69df3bb75b812866ca67e674a57761f70a039c0b279
7
+ data.tar.gz: 1c02e24825451683e430ad138607db79412d6ec4fae42294a7b703272c8b1593aaba4258dfe857371241fc7cad6187516d22415e63e07e26da5bff4ad61600d6
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --colour
3
+ --format <%= ENV["CI"] ? 'progress' : 'documentation'%>
@@ -0,0 +1 @@
1
+ freshdesk_api
@@ -0,0 +1 @@
1
+ ruby
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in freshdesk_api.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Anton Maminov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,97 @@
1
+ # Freshdesk API Client
2
+
3
+
4
+ A Ruby API client that interfaces with freshdesk.com web service. This client supports regular CRUD operation.
5
+
6
+ Please see [API documentation](http://freshdesk.com/api) for more information.
7
+
8
+ As of now,it supports the following:
9
+
10
+ * Solution Category
11
+ * Solution Folder
12
+ * Solution Article
13
+
14
+
15
+ To experiment with that code, run `bin/console` for an interactive prompt.
16
+
17
+ ## Installation
18
+
19
+ The Freshdesk API client can be installd using Bundler or Rubygems.
20
+
21
+ ### Bundler
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'freshdesk_api'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ ```
32
+ $ bundle
33
+ ```
34
+
35
+ ### Rubygems
36
+
37
+ Or install it yourself as:
38
+
39
+ ```
40
+ $ gem install freshdesk_api
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ Configuration is done through a block returning an instance of `FreshdeskAPI::Client`. The block is mandatory and if not passed, an `ArgumentError` will be thrown.
46
+
47
+ ```ruby
48
+ require 'freshdesk_api'
49
+
50
+ client = FreshdeskAPI::Client.new do |config|
51
+ config.base_url = '<- your-freshdesk-url ->' # e.g. 'https://mydesk.freshdesk.com'
52
+ config.username = 'login.email@freshdesk.com'
53
+ config.password = 'your freshdesk password'
54
+ end
55
+ ```
56
+
57
+ Note: This FreshdeskAPI API client only supports basic authentication at the moment.
58
+
59
+ ## Usage
60
+
61
+ The result of configuration is an instance of `FreshdeskAPI::Client` which can then be used in two different methods.
62
+
63
+ One way to use the client is to pass it in as an argument to individual classes.
64
+
65
+ ```ruby
66
+ FreshdeskAPI::SolutionCategory.create!(client, name: 'API', description: 'API related documents')
67
+ FreshdeskAPI::SolutionArticle.find!(client, id: 1, 1: category_id, folder_id: 1)
68
+ FreshdeskAPI::SolutionFolder.update!(client, id: 1, category_id: 1, name: 'Folder API')
69
+ FreshdeskAPI::SolutionArticle.destroy!(client, id: 1, category_id: 1, folder_id: 1)
70
+ ```
71
+ Another way is to use the instance methods under client.
72
+
73
+ ```ruby
74
+ categories = client.solution_categories
75
+ category = categories.create!(name: 'API', description: 'API related documents')
76
+ category.update!(name: 'API v2', description: 'API related documents v2')
77
+ category = categories.find!(id: 1)
78
+ category.destroy!
79
+ ```
80
+
81
+ The methods under `FreshdeskAPI::Client` (such as `.solution_categories`) return an instance of `FreshdeskAPI::Collection` a lazy-loaded list of that resource.
82
+
83
+ Actual requests may not be sent until an explicit `FreshdeskAPI::Collection#all!`.
84
+
85
+ ## Development
86
+
87
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
88
+
89
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
90
+
91
+ ## Contributing
92
+
93
+ 1. Fork it ( https://github.com/mamantoha/freshdesk_api_client_rb/fork )
94
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
95
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
96
+ 4. Push to the branch (`git push origin my-new-feature`)
97
+ 5. Create a new Pull Request
@@ -0,0 +1,17 @@
1
+ require 'rake/testtask'
2
+ require "bundler/gem_tasks"
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+ rescue LoadError
7
+ end
8
+
9
+ if defined?(RSpec)
10
+ desc "Run specs"
11
+ RSpec::Core::RakeTask.new("spec") do |t|
12
+ t.pattern = "spec/core/**/*_spec.rb"
13
+ end
14
+
15
+ desc 'Default: run specs.'
16
+ task default: 'spec'
17
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "freshdesk_api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'freshdesk_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "freshdesk_api"
8
+ spec.version = FreshdeskAPI::VERSION
9
+ spec.authors = ["Anton Maminov"]
10
+ spec.email = ["anton.linux@gmail.com"]
11
+
12
+ spec.summary = %q{Freshdesk REST API Client}
13
+ spec.description = %q{Ruby wrapper for the REST API at http://freshdesk.com. Documentation at http://freshdesk.com/api.}
14
+ spec.homepage = "https://github.com/mamantoha/freshdesk_api_client_rb"
15
+
16
+ spec.required_ruby_version = ">= 2.0.0"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_runtime_dependency "activesupport"
24
+ spec.add_runtime_dependency "rest-client"
25
+ spec.add_runtime_dependency "multi_json"
26
+ spec.add_runtime_dependency "deep_merge"
27
+
28
+ spec.add_development_dependency "byebug"
29
+ spec.add_development_dependency "bundler", "~> 1.9"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec"
32
+ spec.add_development_dependency "webmock"
33
+ end
@@ -0,0 +1,3 @@
1
+ module FreshdeskAPI; end
2
+
3
+ require "freshdesk_api/client"
@@ -0,0 +1,194 @@
1
+ module FreshdeskAPI
2
+
3
+ module ResponseHandler
4
+ def handle_response(response)
5
+ response = MultiJson.load(response, symbolize_keys: true)
6
+ if response[response_namespace]
7
+ @attributes.replace(@attributes.deep_merge(response[response_namespace]))
8
+ end
9
+ end
10
+ end
11
+
12
+ module Read
13
+ def self.extended(klass)
14
+ klass.send(:include, ResponseHandler)
15
+ end
16
+
17
+ # Finds a resource by an id and any options passed in
18
+ # @param [Client] client The {Client} object to be used
19
+ # @param [Hash] option Any additional GET parameters to be added
20
+ def find!(client, options = {})
21
+ @client = client # so we can use client.logger in rescue
22
+ raise ArgumentError, 'No :id given' unless options[:id]
23
+
24
+ path = api_url(options) + "/#{options[:id]}"
25
+
26
+ response = client.make_request!(path, :get)
27
+
28
+ new(@client).tap do |resource|
29
+ resource.attributes.merge!(options)
30
+ resource.handle_response(response)
31
+ end
32
+ end
33
+
34
+ # Finds, returning nil if it fails
35
+ def find(client, options = {}, &block)
36
+ find!(client, options, &block)
37
+ rescue FreshdeskAPI::Error::ClientError => e
38
+ nil
39
+ end
40
+ end
41
+
42
+ module Save
43
+ include ResponseHandler
44
+
45
+ # If this resource hasn't been deleted, then create or save it.
46
+ # Executes a POST if it is a {Data#new_record?}, otherwise a PUT.
47
+ # @return [Resource] created or updated object
48
+ def save!(options = {})
49
+ return false if respond_to?(:destroyed?) && destroyed?
50
+
51
+ options = { request_namespace => attributes }
52
+
53
+ if new_record?
54
+ method = :post
55
+ req_path = api_url(options)
56
+ else
57
+ method = :put
58
+ req_path = api_url(options) + "/#{id}"
59
+ end
60
+
61
+ response = @client.make_request!(req_path, method, options)
62
+
63
+ handle_response(response)
64
+ return self
65
+ end
66
+
67
+ # Saves, returning false if it fails and attachibg the errors
68
+ def save(options = {}, &block)
69
+ save!(options, &block)
70
+ rescue FreshdeskAPI::Error::RecordInvalid => e
71
+ @errors = e.errors
72
+ false
73
+ rescue FreshdeskAPI::Error::ClientError
74
+ false
75
+ end
76
+ end
77
+
78
+ module Create
79
+ include Save
80
+
81
+ def self.included(base)
82
+ base.extend(ClassMethods)
83
+ end
84
+
85
+ module ClassMethods
86
+ # Create a resource given the attributes passed in.
87
+ # @param [Client] client The {Client} object to be used
88
+ # @param [Hash] attributes The attributes to create.
89
+ def create!(client, attributes = {}, &block)
90
+ response = nil
91
+ new(client, attributes).tap do |resource|
92
+ response = resource.save!(&block)
93
+ end
94
+
95
+ response
96
+ end
97
+
98
+ # Create a resource, returning nil if it fails
99
+ def create(client, attributes = {}, &block)
100
+ create!(client, attributes, &block)
101
+ rescue FreshdeskAPI::Error::ClientError
102
+ nil
103
+ end
104
+ end
105
+ end
106
+
107
+ module Update
108
+ include Save
109
+
110
+ def self.included(base)
111
+ base.extend(ClassMethods)
112
+ end
113
+
114
+ def update!(attributes = {})
115
+ self.attributes.merge!(attributes)
116
+ self.save!
117
+ end
118
+
119
+ def update(attributes = {})
120
+ update!(attributes = {})
121
+ rescue FreshdeskAPI::Error::ClientError
122
+ false
123
+ end
124
+
125
+ module ClassMethods
126
+ # Updates a resource given the id passed in
127
+ # @params [Client] client The {Client} object to be used
128
+ # @param [Hash] attributes The attributes to update. Default to {}
129
+ def update!(client, attributes = {}, &block)
130
+ response = nil
131
+ new(client, id: attributes.delete(:id)).tap do |resource|
132
+ resource.attributes.merge!(attributes)
133
+ response = resource.save!(&block)
134
+ end
135
+
136
+ response
137
+ end
138
+
139
+ # Updates a resource, returning nil if it fails
140
+ def update(client, attributes = {}, &block)
141
+ update!(client, attributes, &block)
142
+ rescue FreshdeskAPI::Error::ClientError
143
+ false
144
+ end
145
+ end
146
+ end
147
+
148
+ module Destroy
149
+ def self.included(klass)
150
+ klass.extend(ClassMethods)
151
+ end
152
+
153
+ # Has this object been deleted?
154
+ def destroyed?
155
+ @destroyed ||= false
156
+ end
157
+
158
+ # If this resource hasn't already been deleted, then do so.
159
+ # instance method
160
+ # @return [Boolean] Success?
161
+ def destroy!
162
+ return false if destroyed? || new_record?
163
+
164
+ path = api_url + "/#{id}"
165
+ @client.make_request!(path, :delete)
166
+
167
+ @destroyed = true
168
+ end
169
+
170
+ # instance method
171
+ def destroy
172
+ destroy!
173
+ rescue FreshdeskAPI::Error::ClientError
174
+ false
175
+ end
176
+
177
+ module ClassMethods
178
+ # Deteles a resource given the id passed in.
179
+ # @params [Client] client The {Client} object to be used
180
+ # @param [Hash] attributes The optional parameters to pass. Defaults to {}
181
+ def destroy!(client, attributes = {}, &block)
182
+ new(client, attributes).destroy!(&block)
183
+ true
184
+ end
185
+
186
+ def destroy(client, attributes = {}, &block)
187
+ destroy!(client, attributes, &block)
188
+ rescue FreshdeskAPI::Error::ClientError
189
+ false
190
+ end
191
+ end
192
+
193
+ end
194
+ end
@@ -0,0 +1,113 @@
1
+ require 'active_support/core_ext/string'
2
+ require 'rest_client'
3
+ require 'multi_json'
4
+ require 'deep_merge'
5
+
6
+ require 'freshdesk_api/version'
7
+ require 'freshdesk_api/helpers'
8
+ require 'freshdesk_api/configuration'
9
+ require 'freshdesk_api/resource'
10
+ require 'freshdesk_api/collection'
11
+ require 'freshdesk_api/error'
12
+
13
+ # Supported API resources
14
+ require 'freshdesk_api/resources/solution_category'
15
+ require 'freshdesk_api/resources/solution_folder'
16
+ require 'freshdesk_api/resources/solution_article'
17
+
18
+ module FreshdeskAPI
19
+ # The top-level class that handles configuration and connection to the Freshdesk API.
20
+ class Client
21
+ # @return [Configuration] Config instance
22
+ attr_reader :config
23
+
24
+ # Handles resources such as 'tickets'.
25
+ # @return [Collection] Collection instance for resource
26
+ def method_missing(method, *args, &block)
27
+ method = method.to_s
28
+ method_class = method_as_class(method)
29
+ options = args.last.is_a?(Hash) ? args.pop : {}
30
+
31
+ FreshdeskAPI::Collection.new(self, method_class, options)
32
+ end
33
+
34
+ # Creates a new {Client} instance and yields {#config}.
35
+ #
36
+ # Requires a block to be given.
37
+ #
38
+ # Does basic configuration constraints:
39
+ # * {Configuration#base_url} must be https unless {Configuration#allow_http} is set.
40
+ def initialize
41
+ raise ArgumentError, 'block not given' unless block_given?
42
+
43
+ @config = FreshdeskAPI::Configuration.new
44
+
45
+ yield config
46
+
47
+ check_url
48
+ set_default_logger
49
+ end
50
+
51
+ # Creates a connection if there is none, otherwise returns the existing connection.
52
+ #
53
+ # @return [RestClient::Resouce] RestClient connection for the client
54
+ def connection
55
+ @connection ||= build_connection
56
+ end
57
+
58
+ def make_request!(path, method, options = {})
59
+ response = nil
60
+ connection[path].send(method, options) { |resp, req, result|
61
+ case resp.code
62
+ when 302
63
+ # Connection to the server failed. Please check username/password
64
+ when 404
65
+ raise Error::ResourceNotFound
66
+ when 406
67
+ raise Error::NotAcceptable
68
+ when 400...600
69
+ raise Error::NetworkError
70
+ end
71
+ response = resp
72
+ }
73
+ return response
74
+ rescue Exception => e
75
+ raise Error::ClientError.new(e)
76
+ end
77
+
78
+ protected
79
+
80
+ # Called by {#connection} to build a connection.
81
+ #
82
+ # Request logger if logger is not nil
83
+ def build_connection
84
+ RestClient::Resource.new(config.base_url, config.options.merge(auth_options))
85
+ end
86
+
87
+ # HTTP Basic Authentication credentials
88
+ def auth_options
89
+ { user: config.username, password: config.password }
90
+ end
91
+
92
+ private
93
+
94
+ def method_as_class(method)
95
+ klass_as_string = ("FreshdeskAPI::" + method.to_s.singularize.classify).constantize
96
+ end
97
+
98
+ def check_url
99
+ if !config.allow_http && config.base_url !~ /^https/
100
+ raise ArgumentError, "freshdesk_api is ssl only; url must begin with https://"
101
+ end
102
+ end
103
+
104
+ def set_default_logger
105
+ if config.logger.nil? || config.logger == true
106
+ require 'logger'
107
+ config.logger = Logger.new($stderr)
108
+ config.logger.level = Logger::WARN
109
+ end
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,89 @@
1
+ module FreshdeskAPI
2
+ # Represents a collection of resources
3
+ class Collection
4
+ attr_reader :resources
5
+ attr_reader :resource_class
6
+
7
+ # Creates a new Collection instance. Does not fetch resources.
8
+ # @param [Client] client The {Client} to use.
9
+ # @param [String] resource The resource being collected.
10
+ # @param [Hash] options Any additional options to be passed in.
11
+ def initialize(client, resource, options = {})
12
+ @client = client
13
+ @resource_class = resource
14
+ @resource = resource.resource_name
15
+ @options = options
16
+
17
+ methods = %w{ create find update destroy }
18
+ methods += methods.map { |method| method + '!' }
19
+ methods.each do |deferrable|
20
+ # Passes arguments and the proper path to the resource class method.
21
+ # @param [Hash] options Options or attributes to pass
22
+ define_singleton_method deferrable do |*args|
23
+ unless @resource_class.respond_to?(deferrable)
24
+ raise NoMethodError.new("undefined method \"#{deferrable}\" for #{@resource_class}", deferrable, args)
25
+ end
26
+
27
+ opts = args.last.is_a?(Hash) ? args.pop : {}
28
+ @resource_class.send(deferrable, @client, opts)
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ # The API path to this collection
35
+ def path
36
+ @resource_class.api_url(@options)
37
+ end
38
+
39
+ # Execute actual GET from API and load resources into proper class.
40
+ # # @return [Array] All resource
41
+ def all!(options = {})
42
+ @options.merge!(options)
43
+
44
+ response = get_response(path)
45
+ handle_response(response.body)
46
+
47
+ @resources
48
+ end
49
+
50
+ def get_response(path)
51
+ @client.connection[path].send(:get, @options)
52
+ end
53
+
54
+ def handle_response(response_body)
55
+ results = MultiJson.load(response_body, symbolize_keys: true)
56
+
57
+ if results.is_a?(Hash)
58
+ results = FreshdeskAPI::Helpers.deep_hash_access(results, @resource_class.collection_namespace)
59
+ elsif results.is_a?(Array)
60
+ results = results.map { |r| r[@resource_class.collection_namespace.to_sym] }
61
+ else
62
+ raise "Expected a Hash or Array for response body, got #{result.inspect}"
63
+ end
64
+
65
+ @resources = results.map do |res|
66
+ wrap_resource(res)
67
+ end
68
+ end
69
+
70
+ def wrap_resource(res)
71
+ @resource_class.new(@client, res)
72
+ end
73
+
74
+ # @private
75
+ def to_s
76
+ if @resources
77
+ @resources.inspect
78
+ else
79
+ inspect = []
80
+ inspect << "options=#{@options.inspect}" if @options.any?
81
+ "#{@resource.singularize} collection [#{inspect.join(',')}]"
82
+ end
83
+
84
+ end
85
+ alias :inspect :to_s
86
+
87
+ end
88
+
89
+ end
@@ -0,0 +1,51 @@
1
+ module FreshdeskAPI
2
+ # Holds the configuration options for the client and connection
3
+ class Configuration
4
+ # @return [String] The basic auth username
5
+ attr_accessor :username
6
+
7
+ # @return [String] The basic auth password.
8
+ attr_accessor :password
9
+
10
+ # @return [String] The basic auth token.
11
+ attr_accessor :apitoken
12
+
13
+ # @return [String] The API url. Must be https unless {#allow_http} is set.
14
+ attr_accessor :base_url
15
+
16
+ # @return [Logger] Logger to use when logging requests.
17
+ attr_accessor :logger
18
+
19
+ # @return [Hash] Client configurations
20
+ attr_accessor :client_options
21
+
22
+ # @return [Boolean] Whether to allow non-HTTPS connections for development purposes.
23
+ attr_accessor :allow_http
24
+
25
+ # :read_timeout and :open_timeout are how long to wait for a response and
26
+ # to open a connection, in seconds. Pass nil to disable the timeout.
27
+ attr_accessor :open_timeout
28
+ attr_accessor :read_timeout
29
+
30
+ def initialize
31
+ @client_options = {}
32
+ end
33
+
34
+ # Sets accept and user_agent headers, and url
35
+ #
36
+ # @return [Hash] RestClient-formatted hash of options.
37
+ def options
38
+ {
39
+ headers: {
40
+ accept: :json,
41
+ content_type: :json,
42
+ accept_encoding: 'gzip ,deflate',
43
+ user_agent: "FreshdeskAPI API #{FreshdeskAPI::VERSION}"
44
+ },
45
+ read_timeout: nil,
46
+ open_timeout: nil,
47
+ base_url: @base_url
48
+ }.merge(client_options)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,23 @@
1
+ module FreshdeskAPI
2
+ module Error
3
+ class ClientError < StandardError; end
4
+
5
+ class RecordInvalid < ClientError
6
+ attr_accessor :response, :errors
7
+
8
+ def initialize(response)
9
+ @response = response
10
+ binding.pry
11
+ end
12
+
13
+ def to_s
14
+ "#{self.class.name}: #{@errors.to_s}"
15
+ end
16
+ end
17
+
18
+ class NotAcceptable < ClientError; end
19
+ class ResourceNotFound < ClientError; end
20
+ class NetworkError < ClientError; end
21
+
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module FreshdeskAPI
2
+ # @private
3
+ module Helpers
4
+ def self.deep_hash_access(hash, path)
5
+ path.split('/').each do |p|
6
+ if p.to_i.to_s == p
7
+ hash = hash[p.to_i]
8
+ else
9
+ hash = hash[p.to_s] || hash[p.to_sym]
10
+ end
11
+ break unless hash
12
+ end
13
+ hash
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,80 @@
1
+ require 'freshdesk_api/actions'
2
+
3
+ module FreshdeskAPI
4
+ # Represents a resource that only holds data.
5
+ class Data
6
+ # @return [Hash] The resource's attributes
7
+ attr_reader :attributes
8
+
9
+ # @return [Array] The last received errors
10
+ attr_accessor :errors
11
+
12
+ class << self
13
+ # The singular resource name taken from the class name (e.g. FreshdeskAPI::SoulutionCategory -> solution_category)
14
+ def singular_resource_name
15
+ @singular_respurce_name ||= to_s.split('::').last.underscore
16
+
17
+ end
18
+
19
+ # The resource name taken from the class name (e.g. FreshdeskAPI::SolutionCatogory -> solution_categories)
20
+ def resource_name
21
+ @resource_name ||= singular_resource_name.pluralize
22
+ end
23
+ end
24
+
25
+ # Create a new resource instance.
26
+ # @param [Client] client The client to use
27
+ # @param [Hash] attributes The optional attributes that describe the resource
28
+ def initialize(client, attributes = {})
29
+ raise "Expected a Hash for attributes, got #{attributes.inspect}" unless attributes.is_a?(Hash)
30
+ @client = client
31
+ @attributes = attributes
32
+ end
33
+
34
+ # Returns the resource id of the object or nil
35
+ def id
36
+ attributes.key?(:id) ? attributes[:id] : nil
37
+ end
38
+
39
+ # Has this been object been created server-side? Does this by checking for an id.
40
+ def new_record?
41
+ id.nil?
42
+ end
43
+
44
+ # @private
45
+ def to_s
46
+ "#{self.class.singular_resource_name}: #{attributes.inspect}"
47
+ end
48
+ alias :inspect :to_s
49
+
50
+ # @private
51
+ def inspect
52
+ "#<#{self.class.name} #{@attributes.to_hash.inspect}>"
53
+ end
54
+
55
+ # Compares resources by class and id. If id is nil, then by object_id
56
+ def ==(other)
57
+ return true if other.object_id == self.object_id
58
+
59
+ if other && !other.is_a?(Data)
60
+ warn "Trying to compare #{other.class} to a Resource from #{caller.first}"
61
+ end
62
+
63
+ if other.is_a?(Data)
64
+ other.id && other.id == id
65
+ else
66
+ false
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ # Represents a resource that can CRUD (create, read, update, destroy)
73
+ class Resource < Data
74
+ include Create
75
+ extend Read
76
+ include Update
77
+ include Destroy
78
+ end
79
+
80
+ end
@@ -0,0 +1,31 @@
1
+ require 'freshdesk_api/resource'
2
+
3
+ module FreshdeskAPI
4
+ class SolutionArticle < Resource
5
+ # Need to specify the category_id and folder_id in url
6
+
7
+ def api_url(options = {})
8
+ "/solution/categories/%{category_id}/folders/%{folder_id}/articles" % attributes
9
+ end
10
+
11
+ def request_namespace
12
+ 'solution_article'
13
+ end
14
+
15
+ def response_namespace
16
+ :article
17
+ end
18
+
19
+ class << self
20
+ def api_url(options = {})
21
+ "/solution/categories/%{category_id}/folders/%{folder_id}/articles" % options
22
+ end
23
+
24
+ def collection_namespace
25
+ 'folder/articles'
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'freshdesk_api/resource'
2
+
3
+ module FreshdeskAPI
4
+ class SolutionCategory < Resource
5
+ def api_url(options = {})
6
+ "/solution/categories"
7
+ end
8
+
9
+ def request_namespace
10
+ 'solution_category'
11
+ end
12
+
13
+ def response_namespace
14
+ :category
15
+ end
16
+
17
+
18
+ class << self
19
+ def api_url(options = {})
20
+ "/solution/categories"
21
+ end
22
+
23
+ def collection_namespace
24
+ 'category'
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ require 'freshdesk_api/resource'
2
+
3
+ module FreshdeskAPI
4
+ class SolutionFolder < Resource
5
+ # Need to specify category_id in url
6
+
7
+ def api_url(options = {})
8
+ "/solution/categories/%{category_id}/folders" % attributes
9
+ end
10
+
11
+ def request_namespace
12
+ 'solution_folder'
13
+ end
14
+
15
+ def response_namespace
16
+ :folder
17
+ end
18
+
19
+ class << self
20
+ def api_url(options = {})
21
+ "/solution/categories/%{category_id}/folders" % options
22
+ end
23
+
24
+ def collection_namespace
25
+ 'category/folders'
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module FreshdeskAPI
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: freshdesk_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Anton Maminov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: multi_json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: deep_merge
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.9'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.9'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Ruby wrapper for the REST API at http://freshdesk.com. Documentation
140
+ at http://freshdesk.com/api.
141
+ email:
142
+ - anton.linux@gmail.com
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".rspec"
148
+ - ".ruby-gemset"
149
+ - ".ruby-version"
150
+ - Gemfile
151
+ - LICENSE
152
+ - README.md
153
+ - Rakefile
154
+ - bin/console
155
+ - bin/setup
156
+ - freshdesk_api.gemspec
157
+ - lib/freshdesk_api.rb
158
+ - lib/freshdesk_api/actions.rb
159
+ - lib/freshdesk_api/client.rb
160
+ - lib/freshdesk_api/collection.rb
161
+ - lib/freshdesk_api/configuration.rb
162
+ - lib/freshdesk_api/error.rb
163
+ - lib/freshdesk_api/helpers.rb
164
+ - lib/freshdesk_api/resource.rb
165
+ - lib/freshdesk_api/resources/solution_article.rb
166
+ - lib/freshdesk_api/resources/solution_category.rb
167
+ - lib/freshdesk_api/resources/solution_folder.rb
168
+ - lib/freshdesk_api/version.rb
169
+ homepage: https://github.com/mamantoha/freshdesk_api_client_rb
170
+ licenses: []
171
+ metadata: {}
172
+ post_install_message:
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: 2.0.0
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubyforge_project:
188
+ rubygems_version: 2.4.6
189
+ signing_key:
190
+ specification_version: 4
191
+ summary: Freshdesk REST API Client
192
+ test_files: []
193
+ has_rdoc: