endow 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 034bba2791918b03fcc0184b4db0e76a0131b1eb
4
+ data.tar.gz: 40b310f28ce7f8acba88bfb209959d8ac46cbd72
5
+ SHA512:
6
+ metadata.gz: 8ffd32c6d7977a8bf86312a1b85bb0336376bebc9238c3f5914dcc32407cfb4ce0efa3fd27415d5820c122f4eb15e6532c415e6a4650fb46365721ee6a677eb3
7
+ data.tar.gz: cb53e92145b41b15a5be074fe441cdb52c63f669fb0a5eafe22db5b53442531d98ba580424849d5ff29368e773c1de27224e8b6a4296e6674bc34913ed1dee10
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ gemdev
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p247
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in endow.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Jason Harrelson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # Endow
2
+
3
+ A library to assist in consuming API endpoints.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'endow'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install endow
19
+
20
+
21
+ ## Usage
22
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/endow.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'endow/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "endow"
8
+ spec.version = Endow::VERSION
9
+ spec.authors = ["Jason Harrelson"]
10
+ spec.email = ["jason@lookforwardenterprises.com"]
11
+ spec.description = %q{A library to assist in consuming API endpoints.}
12
+ spec.summary = %q{A library to assist in consuming API endpoints.}
13
+ spec.homepage = "https://github.com/midas/endow"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 3"
22
+ spec.add_dependency "httpi"#, "~> 1"
23
+ spec.add_dependency "multi_json"#, "~> 1"
24
+ spec.add_dependency "retryable-rb", "~> 1"
25
+ spec.add_dependency "wisper"#, "~> 1"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.3"
28
+ spec.add_development_dependency "rake"
29
+ end
data/lib/ansi.rb ADDED
@@ -0,0 +1,36 @@
1
+ class ANSI
2
+
3
+ def self.resolve_text( color, &block )
4
+ text = nil
5
+ if block_given?
6
+ text = block.call + reset
7
+ end
8
+ "\e[#{chart[color.to_sym]}m#{text}"
9
+ end
10
+
11
+ def self.reset
12
+ "\e[0m"
13
+ end
14
+
15
+ def self.chart
16
+ {
17
+ black: 30,
18
+ red: 31,
19
+ green: 32,
20
+ yellow: 33,
21
+ blue: 34,
22
+ magenta: 35,
23
+ cyan: 36,
24
+ white: 37
25
+ }
26
+ end
27
+
28
+ chart.keys.each do |color|
29
+
30
+ define_singleton_method color do |&block|
31
+ resolve_text color, &block
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,13 @@
1
+ module Endow
2
+ class Configuration
3
+
4
+ def logger
5
+ @logger
6
+ end
7
+
8
+ def logger=( logger )
9
+ @logger = logger
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,238 @@
1
+ module Endow
2
+ module Endpoint
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Retryable
8
+ include ErrorHandling
9
+ include Logging
10
+ include Wisper::Publisher
11
+ end
12
+
13
+ def initialize
14
+ set_content nil
15
+ end
16
+
17
+ def call
18
+ with_graceful_error_handling do
19
+ attempt = 0
20
+ retryable on: retryable_errors,
21
+ times: retryable_times,
22
+ sleep: retryable_sleep do
23
+ attempt += 1
24
+ log_connection( self, attempt )
25
+
26
+ if success_error_codes.include?( response.code )
27
+ handle_successful_response
28
+ else
29
+ _handle_unsuccessful_response
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ def request_url
36
+ request.url
37
+ end
38
+
39
+ def request_query
40
+ request.query
41
+ end
42
+
43
+ def request_body
44
+ request.body
45
+ end
46
+
47
+ def request_headers
48
+ request.headers
49
+ end
50
+
51
+ def to_s
52
+ "#<#{self.class.name}:#{object_id} " +
53
+ "@verb=#{http_verb.inspect} " +
54
+ "@url=#{request_url.to_s.inspect} " +
55
+ "@query=#{request_query.inspect} " +
56
+ "@body=#{request_body.inspect } " +
57
+ "@headers=#{request_headers.inspect}>"
58
+ end
59
+
60
+ protected
61
+
62
+ def response
63
+ @response ||= HTTPI.request( http_verb, request )
64
+ end
65
+
66
+ def request
67
+ @request ||= HTTPI::Request.new( request_params ).tap do |req|
68
+ req.headers = default_headers
69
+ req.auth.ssl.verify_mode = ssl_verify_mode
70
+ end
71
+ end
72
+
73
+ def request_params
74
+ {
75
+ url: url,
76
+ open_timeout: open_timeout_in_seconds,
77
+ read_timeout: read_timeout_in_seconds
78
+ }.reject { |k,v| v.blank? }
79
+ end
80
+
81
+ def handle_successful_response
82
+ check_response_on_success( response )
83
+
84
+ response_wrapper_class.new( decode_body( response.body )).tap do |response_body|
85
+ publish :success,
86
+ response_body,
87
+ response
88
+ end
89
+ end
90
+
91
+ def check_response_on_success( response )
92
+ # purposefully empty
93
+ end
94
+
95
+ def response_wrapper_class
96
+ raise NotImplementedError
97
+ end
98
+
99
+ def handle_unsuccessful_response
100
+ publish :error, response
101
+ end
102
+
103
+ def _handle_unsuccessful_response
104
+ custom_handler_method = "handle_unsuccessful_response_#{response.code}"
105
+
106
+ unless respond_to?( custom_handler_method )
107
+ handle_unsuccessful_response
108
+ return
109
+ end
110
+
111
+ send( custom_handler_method )
112
+ end
113
+
114
+ def set_content( content )
115
+ send "set_content_as_#{content_type_name}", content
116
+ end
117
+
118
+ def set_content_as_no_content_type_specified( content )
119
+ if http_verb.to_sym == :get
120
+ request.query = make_query_string( content )
121
+ elsif http_verb.to_sym == :post
122
+ request.body = make_query_string( content )
123
+ end
124
+ end
125
+
126
+ def set_content_as_application_json( content )
127
+ request.body = MultiJson.dump( content || {} )
128
+ end
129
+
130
+ def decode_body( content )
131
+ send "decode_body_as_#{accept_name}", content
132
+ end
133
+
134
+ def decode_body_as_no_accept_specified( content )
135
+ content
136
+ end
137
+
138
+ def decode_body_as_application_json( content )
139
+ MultiJson.load( content )
140
+ end
141
+
142
+ def decode_body_as_application_xml( content )
143
+ raise NotImplementedError
144
+ end
145
+
146
+ def content_type_name
147
+ content_type.blank? ?
148
+ :no_content_type_specified :
149
+ content_type.split( '/' ).join( '_' )
150
+ end
151
+
152
+ def accept_name
153
+ accept.blank? ?
154
+ :no_accept_specified :
155
+ accept.split( '/' ).join( '_' )
156
+ end
157
+
158
+ def default_headers
159
+ {
160
+ 'Accept' => accept,
161
+ 'Content-Type' => content_type,
162
+ }.reject { |k,v| v.blank? }
163
+ end
164
+
165
+ def make_query_string( content )
166
+ content.merge( base_content ).to_query
167
+ end
168
+
169
+ def base_content
170
+ {}
171
+ end
172
+
173
+ def url
174
+ File.join( base_url, endpoint )
175
+ end
176
+
177
+ def http_verb
178
+ :get
179
+ end
180
+
181
+ def success_error_codes
182
+ [200]
183
+ end
184
+
185
+ def open_timeout_in_seconds
186
+ 15
187
+ end
188
+
189
+ def read_timeout_in_seconds
190
+ 15
191
+ end
192
+
193
+ def retryable_times
194
+ 1
195
+ end
196
+
197
+ def retryable_sleep
198
+ false
199
+ end
200
+
201
+ def accept
202
+ nil
203
+ end
204
+
205
+ def accept_version
206
+ raise NotImplementedError
207
+ end
208
+
209
+ def content_type
210
+ nil
211
+ end
212
+
213
+ def endpoint
214
+ raise NotImplementedError
215
+ end
216
+
217
+ def authentication_token_key
218
+ raise NotImplementedError
219
+ end
220
+
221
+ def ssl_verify_mode
222
+ raise NotImplementedError
223
+ end
224
+
225
+ def ensure_date( time_or_string )
226
+ return nil if time_or_string.blank?
227
+ if time_or_string.is_a?( String )
228
+ begin
229
+ return Date.strptime( time_or_string, Date::DATE_FORMATS[:api_internal] )
230
+ rescue ArgumentError
231
+ return Date.strptime( time_or_string, Date::DATE_FORMATS[:isdn] )
232
+ end
233
+ end
234
+ time_or_string.to_date
235
+ end
236
+
237
+ end
238
+ end
@@ -0,0 +1,29 @@
1
+ module Endow
2
+ module ErrorHandling
3
+
4
+ protected
5
+
6
+ def retryable_errors
7
+ graceful_errors
8
+ end
9
+
10
+ def graceful_errors
11
+ graceful_errors_map.keys
12
+ end
13
+
14
+ def graceful_errors_map
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def with_graceful_error_handling( &block )
19
+ block.call
20
+ rescue *graceful_errors => e
21
+ msg = "#{self.class.name}: #{graceful_errors_map[e.class][:msg]}"
22
+ log_graceful_error( msg )
23
+ raise graceful_errors_map[e.class][:klass],
24
+ msg,
25
+ e.backtrace
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ module Endow
2
+ class Logger
3
+
4
+ #class_attribute :logger
5
+ #self.logger = nil
6
+
7
+ def self.log_connection( service, attempt )
8
+ log "#{green_prefix} #{service.class.name} (Attempt #{attempt})"
9
+ end
10
+
11
+ def self.log_graceful_error( msg )
12
+ log "#{red_prefix} #{msg}"
13
+ end
14
+
15
+ def self.log( msg )
16
+ return unless logger
17
+ #TODO make this more adaptable
18
+ logger.info( msg )
19
+ end
20
+
21
+ def self.logger
22
+ Endow.configuration.logger
23
+ end
24
+
25
+ def self.green_prefix
26
+ #TODO change to another ANSI library
27
+ "#{indention}[#{ANSI.green { label }}]"
28
+ end
29
+
30
+ def self.red_prefix
31
+ #TODO change to another ANSI library
32
+ "#{indention}[#{ANSI.red { error_label }}]"
33
+ end
34
+
35
+ def self.label
36
+ "Service Connection"
37
+ end
38
+
39
+ def self.error_label
40
+ "Service ERROR"
41
+ end
42
+
43
+ def self.indention
44
+ " "
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ module Endow
2
+ module Logging
3
+
4
+ def log_connection( service, attempt )
5
+ Endow::Logger.log_connection( service, attempt )
6
+ end
7
+
8
+ def log_graceful_error( msg )
9
+ Endow::Logger.log_graceful_error( msg )
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Endow
2
+ VERSION = "0.1.0"
3
+ end
data/lib/endow.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext/string'
3
+ require "httpi"
4
+ require "multi_json"
5
+ require "retryable"
6
+ require "wisper"
7
+ require "endow/version"
8
+ require "ansi"
9
+
10
+ module Endow
11
+
12
+ autoload :Configuration, 'endow/configuration'
13
+ autoload :Endpoint, 'endow/endpoint'
14
+ autoload :ErrorHandling, 'endow/error_handling'
15
+ autoload :Logger, 'endow/logger'
16
+ autoload :Logging, 'endow/logging'
17
+
18
+ def self.configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+
22
+ def self.configure
23
+ yield( configuration ) if block_given?
24
+ end
25
+
26
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: endow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jason Harrelson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-21 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: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httpi
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: retryable-rb
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: wisper
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
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.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A library to assist in consuming API endpoints.
112
+ email:
113
+ - jason@lookforwardenterprises.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .ruby-gemset
120
+ - .ruby-version
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - endow.gemspec
126
+ - lib/ansi.rb
127
+ - lib/endow.rb
128
+ - lib/endow/configuration.rb
129
+ - lib/endow/endpoint.rb
130
+ - lib/endow/error_handling.rb
131
+ - lib/endow/logger.rb
132
+ - lib/endow/logging.rb
133
+ - lib/endow/version.rb
134
+ homepage: https://github.com/midas/endow
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.0.5
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: A library to assist in consuming API endpoints.
158
+ test_files: []