freshdesk_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: