vertebrae 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +80 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/api.rb +155 -0
- data/lib/authorization.rb +17 -0
- data/lib/configuration.rb +105 -0
- data/lib/connection.rb +80 -0
- data/lib/constants.rb +31 -0
- data/lib/core_ext/array.rb +5 -0
- data/lib/railties.rb +7 -0
- data/lib/request/basic_auth.rb +26 -0
- data/lib/response/raise_error.rb +19 -0
- data/lib/vertebrae.rb +40 -0
- data/spec/api_spec.rb +36 -0
- data/spec/authorization_spec.rb +26 -0
- data/spec/configuration_spec.rb +41 -0
- data/spec/dummy/client.rb +7 -0
- data/spec/dummy/dummy.rb +8 -0
- data/spec/logger_spec.rb +18 -0
- data/spec/spec_helper.rb +23 -0
- data/vertebrae.gemspec +85 -0
- metadata +172 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cacba90d6b51ff109cb06354b8a02a9c85aa3634
|
4
|
+
data.tar.gz: 29bbd9175d2b97240f28fe2d4d7e5907be7202cf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a6bc54a6d292c80f8f9d34d8cfbbebd8c0b5d2d82ccd61485cdd4c602e1b254781c7c22efc03893c4137490b57eed44dd8c30aca743ededf64532857bcb0f1e0
|
7
|
+
data.tar.gz: 406fca22dcddbb196a7c95b2d7ac44c98f427df9f6326b6079cff9431d67d80753f15c66256216da622422cce50a8425bf09b45f2eca8e957c4f10c74c911eb4
|
data/.document
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
vertebrae
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.0.0-p247
|
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
|
5
|
+
gem 'activesupport'
|
6
|
+
gem 'faraday'
|
7
|
+
gem 'faraday_middleware'
|
8
|
+
gem 'hashie'
|
9
|
+
|
10
|
+
|
11
|
+
# Add dependencies to develop your gem here.
|
12
|
+
# Include everything needed to run rake, tests, features, etc.
|
13
|
+
group :development do
|
14
|
+
gem "rspec"
|
15
|
+
gem "bundler"
|
16
|
+
gem "jeweler", "~> 1.8.4"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (4.0.0)
|
5
|
+
i18n (~> 0.6, >= 0.6.4)
|
6
|
+
minitest (~> 4.2)
|
7
|
+
multi_json (~> 1.3)
|
8
|
+
thread_safe (~> 0.1)
|
9
|
+
tzinfo (~> 0.3.37)
|
10
|
+
addressable (2.3.5)
|
11
|
+
atomic (1.1.10)
|
12
|
+
builder (3.2.2)
|
13
|
+
diff-lcs (1.2.4)
|
14
|
+
faraday (0.8.7)
|
15
|
+
multipart-post (~> 1.1)
|
16
|
+
faraday_middleware (0.9.0)
|
17
|
+
faraday (>= 0.7.4, < 0.9)
|
18
|
+
git (1.2.5)
|
19
|
+
github_api (0.10.1)
|
20
|
+
addressable
|
21
|
+
faraday (~> 0.8.1)
|
22
|
+
hashie (>= 1.2)
|
23
|
+
multi_json (~> 1.4)
|
24
|
+
nokogiri (~> 1.5.2)
|
25
|
+
oauth2
|
26
|
+
hashie (2.0.5)
|
27
|
+
highline (1.6.19)
|
28
|
+
httpauth (0.2.0)
|
29
|
+
i18n (0.6.4)
|
30
|
+
jeweler (1.8.6)
|
31
|
+
builder
|
32
|
+
bundler (~> 1.0)
|
33
|
+
git (>= 1.2.5)
|
34
|
+
github_api (= 0.10.1)
|
35
|
+
highline (>= 1.6.15)
|
36
|
+
nokogiri (= 1.5.10)
|
37
|
+
rake
|
38
|
+
rdoc
|
39
|
+
json (1.8.0)
|
40
|
+
jwt (0.1.8)
|
41
|
+
multi_json (>= 1.5)
|
42
|
+
minitest (4.7.5)
|
43
|
+
multi_json (1.7.7)
|
44
|
+
multi_xml (0.5.4)
|
45
|
+
multipart-post (1.2.0)
|
46
|
+
nokogiri (1.5.10)
|
47
|
+
oauth2 (0.9.2)
|
48
|
+
faraday (~> 0.8)
|
49
|
+
httpauth (~> 0.2)
|
50
|
+
jwt (~> 0.1.4)
|
51
|
+
multi_json (~> 1.0)
|
52
|
+
multi_xml (~> 0.5)
|
53
|
+
rack (~> 1.2)
|
54
|
+
rack (1.5.2)
|
55
|
+
rake (10.1.0)
|
56
|
+
rdoc (4.0.1)
|
57
|
+
json (~> 1.4)
|
58
|
+
rspec (2.14.1)
|
59
|
+
rspec-core (~> 2.14.0)
|
60
|
+
rspec-expectations (~> 2.14.0)
|
61
|
+
rspec-mocks (~> 2.14.0)
|
62
|
+
rspec-core (2.14.2)
|
63
|
+
rspec-expectations (2.14.0)
|
64
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
65
|
+
rspec-mocks (2.14.1)
|
66
|
+
thread_safe (0.1.0)
|
67
|
+
atomic
|
68
|
+
tzinfo (0.3.37)
|
69
|
+
|
70
|
+
PLATFORMS
|
71
|
+
ruby
|
72
|
+
|
73
|
+
DEPENDENCIES
|
74
|
+
activesupport
|
75
|
+
bundler
|
76
|
+
faraday
|
77
|
+
faraday_middleware
|
78
|
+
hashie
|
79
|
+
jeweler (~> 1.8.4)
|
80
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 ControlShift Ltd.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= vertebrae
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Contributing to vertebrae
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
* Fork the project.
|
10
|
+
* Start a feature/bugfix branch.
|
11
|
+
* Commit and push until you are happy with your contribution.
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2013 Nathan Woodhull. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
gem.name = "vertebrae"
|
17
|
+
gem.homepage = "http://github.com/controlshift/vertebrae"
|
18
|
+
gem.license = "MIT"
|
19
|
+
gem.summary = %Q{API Client Infrastructure}
|
20
|
+
gem.description = %Q{A set of low level infrastructure and reusable code for building API clients}
|
21
|
+
gem.email = "nathan@controlshiftlabs.com"
|
22
|
+
gem.authors = ["Nathan Woodhull"]
|
23
|
+
# dependencies defined in Gemfile
|
24
|
+
end
|
25
|
+
Jeweler::RubygemsDotOrgTasks.new
|
26
|
+
|
27
|
+
require 'rspec/core'
|
28
|
+
require 'rspec/core/rake_task'
|
29
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
30
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
31
|
+
end
|
32
|
+
|
33
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
35
|
+
spec.rcov = true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => :spec
|
39
|
+
|
40
|
+
require 'rdoc/task'
|
41
|
+
Rake::RDocTask.new do |rdoc|
|
42
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
43
|
+
|
44
|
+
rdoc.rdoc_dir = 'rdoc'
|
45
|
+
rdoc.title = "vertebrae #{version}"
|
46
|
+
rdoc.rdoc_files.include('README*')
|
47
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
48
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/api.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
class API
|
3
|
+
|
4
|
+
include Connection
|
5
|
+
include Request
|
6
|
+
include Authorization
|
7
|
+
|
8
|
+
attr_reader *Configuration.keys
|
9
|
+
|
10
|
+
attr_accessor :current_options
|
11
|
+
|
12
|
+
# Callback to update current configuration options
|
13
|
+
class_eval do
|
14
|
+
Configuration.keys.each do |key|
|
15
|
+
define_method "#{key}=" do |arg|
|
16
|
+
self.instance_variable_set("@#{key}", arg)
|
17
|
+
self.current_options.merge!({:"#{key}" => arg})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Create new API
|
23
|
+
#
|
24
|
+
def initialize(options={}, &block)
|
25
|
+
setup(options)
|
26
|
+
yield_or_eval(&block) if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def yield_or_eval(&block)
|
31
|
+
return unless block
|
32
|
+
block.arity > 0 ? yield(self) : self.instance_eval(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Configure options and process basic authorization
|
36
|
+
#
|
37
|
+
def setup(options={})
|
38
|
+
options = Vertebrae.options.merge(options)
|
39
|
+
self.current_options = options
|
40
|
+
Configuration.keys.each do |key|
|
41
|
+
send("#{key}=", options[key])
|
42
|
+
end
|
43
|
+
process_basic_auth(options[:basic_auth])
|
44
|
+
end
|
45
|
+
|
46
|
+
# Extract login and password from basic_auth parameter
|
47
|
+
#
|
48
|
+
def process_basic_auth(auth)
|
49
|
+
case auth
|
50
|
+
when String
|
51
|
+
self.username, self.password = auth.split(':', 2)
|
52
|
+
when Hash
|
53
|
+
self.username = auth[:username]
|
54
|
+
self.password = auth[:password]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Responds to attribute query or attribute clear
|
59
|
+
def method_missing(method, *args, &block) # :nodoc:
|
60
|
+
case method.to_s
|
61
|
+
when /^(.*)\?$/
|
62
|
+
return !!self.send($1.to_s)
|
63
|
+
when /^clear_(.*)$/
|
64
|
+
self.send("#{$1.to_s}=", nil)
|
65
|
+
else
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Acts as setter and getter for api requests arguments parsing.
|
71
|
+
#
|
72
|
+
# Returns Arguments instance.
|
73
|
+
#
|
74
|
+
def arguments(args=(not_set = true), options={}, &block)
|
75
|
+
if not_set
|
76
|
+
@arguments
|
77
|
+
else
|
78
|
+
@arguments = Arguments.new(self, options).parse(*args, &block)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Scope for passing request required arguments.
|
83
|
+
#
|
84
|
+
def with(args)
|
85
|
+
case args
|
86
|
+
when Hash
|
87
|
+
set args
|
88
|
+
when /.*\/.*/i
|
89
|
+
user, repo = args.split('/')
|
90
|
+
set :user => user, :repo => repo
|
91
|
+
else
|
92
|
+
::Kernel.raise ArgumentError, 'This api does not support passed in arguments'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Set an option to a given value
|
97
|
+
def set(option, value=(not_set=true), ignore_setter=false, &block)
|
98
|
+
raise ArgumentError, 'value not set' if block and !not_set
|
99
|
+
return self if !not_set and value.nil?
|
100
|
+
|
101
|
+
if not_set
|
102
|
+
set_options option
|
103
|
+
return self
|
104
|
+
end
|
105
|
+
|
106
|
+
if respond_to?("#{option}=") and not ignore_setter
|
107
|
+
return __send__("#{option}=", value)
|
108
|
+
end
|
109
|
+
|
110
|
+
define_accessors option, value
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def extract_id_from_response(resp)
|
117
|
+
extract_id_from_location(resp.response.headers["location"])
|
118
|
+
end
|
119
|
+
|
120
|
+
def extract_id_from_location(location)
|
121
|
+
location.scan(/\/(\d+)\/$/).first.first
|
122
|
+
end
|
123
|
+
|
124
|
+
# Set multiple options
|
125
|
+
#
|
126
|
+
def set_options(options)
|
127
|
+
unless options.respond_to?(:each)
|
128
|
+
raise ArgumentError, 'cannot iterate over value'
|
129
|
+
end
|
130
|
+
options.each { |key, value| set(key, value) }
|
131
|
+
end
|
132
|
+
|
133
|
+
def define_accessors(option, value)
|
134
|
+
setter = proc { |val| set option, val, true }
|
135
|
+
getter = proc { value }
|
136
|
+
|
137
|
+
define_singleton_method("#{option}=", setter) if setter
|
138
|
+
define_singleton_method(option, getter) if getter
|
139
|
+
end
|
140
|
+
|
141
|
+
# Dynamically define a method for setting request option
|
142
|
+
#
|
143
|
+
def define_singleton_method(method_name, content=Proc.new)
|
144
|
+
(class << self; self; end).class_eval do
|
145
|
+
undef_method(method_name) if method_defined?(method_name)
|
146
|
+
if String === content
|
147
|
+
class_eval("def #{method_name}() #{content}; end")
|
148
|
+
else
|
149
|
+
define_method(method_name, &content)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
module Authorization
|
3
|
+
|
4
|
+
# Check whether authentication credentials are present
|
5
|
+
def authenticated?
|
6
|
+
(username? && password?)
|
7
|
+
end
|
8
|
+
|
9
|
+
def basic_auth
|
10
|
+
"#{username}:#{password}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def authentication
|
14
|
+
{ :basic_auth => basic_auth }
|
15
|
+
end
|
16
|
+
end # Authorization
|
17
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
module Configuration
|
3
|
+
include Vertebrae::Constants
|
4
|
+
|
5
|
+
|
6
|
+
VALID_OPTIONS_KEYS = [
|
7
|
+
:adapter,
|
8
|
+
:prefix,
|
9
|
+
:ssl,
|
10
|
+
:mime_type,
|
11
|
+
:user_agent,
|
12
|
+
:host,
|
13
|
+
:username,
|
14
|
+
:password,
|
15
|
+
:connection_options,
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
# Other adapters are :typhoeus, :patron, :em_synchrony, :excon, :test
|
19
|
+
DEFAULT_ADAPTER = :net_http
|
20
|
+
|
21
|
+
# The default SSL configuration
|
22
|
+
DEFAULT_SSL = {}
|
23
|
+
|
24
|
+
# By default the <tt>Accept</tt> header will make a request for <tt>JSON</tt>
|
25
|
+
DEFAULT_MIME_TYPE = :json
|
26
|
+
|
27
|
+
# The value sent in the http header for 'User-Agent' if none is set
|
28
|
+
DEFAULT_USER_AGENT = "Vertebrae REST Gem".freeze
|
29
|
+
|
30
|
+
# by default do not set a host. this is specific to AK instance
|
31
|
+
DEFAULT_HOST = nil
|
32
|
+
|
33
|
+
# The api endpoint used to connect to AK if none is set
|
34
|
+
DEFAULT_PREFIX = '/'.freeze
|
35
|
+
|
36
|
+
# By default, don't set a user ame
|
37
|
+
DEFAULT_USERNAME = nil
|
38
|
+
|
39
|
+
# By default, don't set a user password
|
40
|
+
DEFAULT_PASSWORD = nil
|
41
|
+
|
42
|
+
# By default uses the Faraday connection options if none is set
|
43
|
+
DEFAULT_CONNECTION_OPTIONS = {}
|
44
|
+
|
45
|
+
|
46
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
47
|
+
|
48
|
+
# Convenience method to allow for global setting of configuration options
|
49
|
+
def configure
|
50
|
+
yield self
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.extended(base)
|
54
|
+
base.reset!
|
55
|
+
end
|
56
|
+
|
57
|
+
class << self
|
58
|
+
def keys
|
59
|
+
VALID_OPTIONS_KEYS
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def faraday_options(ops)
|
65
|
+
{
|
66
|
+
:headers => {
|
67
|
+
ACCEPT => "application/json;q=0.1",
|
68
|
+
ACCEPT_CHARSET => "utf-8",
|
69
|
+
USER_AGENT => user_agent,
|
70
|
+
CONTENT_TYPE => 'application/json'
|
71
|
+
},
|
72
|
+
:ssl => ops.fetch(:ssl) { ssl },
|
73
|
+
:url => ops.fetch(:endpoint) { self.endpoint(ops) }
|
74
|
+
}.merge(options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def endpoint(ops)
|
78
|
+
h = ops[:host] ? ops[:host] : self.host
|
79
|
+
p = ops[:prefix] ? ops[:prefix] : self.prefix
|
80
|
+
|
81
|
+
"https://#{h}#{p}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def options
|
85
|
+
options = {}
|
86
|
+
VALID_OPTIONS_KEYS.each { |k| options[k] = send(k) }
|
87
|
+
options
|
88
|
+
end
|
89
|
+
|
90
|
+
# Reset configuration options to their defaults
|
91
|
+
#
|
92
|
+
def reset!
|
93
|
+
self.adapter = DEFAULT_ADAPTER
|
94
|
+
self.prefix = DEFAULT_PREFIX
|
95
|
+
self.ssl = DEFAULT_SSL
|
96
|
+
self.mime_type = DEFAULT_MIME_TYPE
|
97
|
+
self.user_agent = DEFAULT_USER_AGENT
|
98
|
+
self.host = DEFAULT_HOST
|
99
|
+
self.username = DEFAULT_USERNAME
|
100
|
+
self.password = DEFAULT_PASSWORD
|
101
|
+
self.connection_options = DEFAULT_CONNECTION_OPTIONS
|
102
|
+
self
|
103
|
+
end
|
104
|
+
end # Configuration
|
105
|
+
end
|
data/lib/connection.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'request/basic_auth'
|
4
|
+
require 'response/raise_error'
|
5
|
+
|
6
|
+
module Vertebrae
|
7
|
+
module Connection
|
8
|
+
|
9
|
+
extend self
|
10
|
+
include Vertebrae::Constants
|
11
|
+
|
12
|
+
ALLOWED_OPTIONS = [
|
13
|
+
:headers,
|
14
|
+
:url,
|
15
|
+
:params,
|
16
|
+
:request,
|
17
|
+
:ssl
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def default_options(options={})
|
21
|
+
Vertebrae.faraday_options(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Default middleware stack that uses default adapter as specified at
|
25
|
+
# configuration stage.
|
26
|
+
#
|
27
|
+
def default_middleware(options={})
|
28
|
+
Proc.new do |builder|
|
29
|
+
builder.use Faraday::Request::Multipart
|
30
|
+
builder.use Faraday::Request::UrlEncoded
|
31
|
+
builder.use Vertebrae::Request::BasicAuth, authentication if authenticated?
|
32
|
+
|
33
|
+
builder.use Faraday::Response::Logger if ENV['DEBUG']
|
34
|
+
unless options[:raw]
|
35
|
+
builder.use FaradayMiddleware::Mashify
|
36
|
+
builder.use FaradayMiddleware::ParseJson
|
37
|
+
end
|
38
|
+
builder.use Vertebrae::Response::RaiseError
|
39
|
+
builder.adapter adapter
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
@connection = nil
|
44
|
+
|
45
|
+
@stack = nil
|
46
|
+
|
47
|
+
def clear_cache
|
48
|
+
@connection = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def caching?
|
52
|
+
!@connection.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Exposes middleware builder to facilitate custom stacks and easy
|
56
|
+
# addition of new extensions such as cache adapter.
|
57
|
+
#
|
58
|
+
def stack(options={}, &block)
|
59
|
+
@stack ||= begin
|
60
|
+
if block_given?
|
61
|
+
Faraday::Builder.new(&block)
|
62
|
+
else
|
63
|
+
Faraday::Builder.new(&default_middleware(options))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a Fraday::Connection object
|
69
|
+
#
|
70
|
+
def connection(options={})
|
71
|
+
conn_options = default_options(options)
|
72
|
+
clear_cache unless options.empty?
|
73
|
+
Vertebrae.logger.debug "OPTIONS:#{conn_options.inspect}"
|
74
|
+
|
75
|
+
@connection ||= Faraday.new(conn_options.merge(:builder => stack(options)))
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/constants.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
module Constants
|
3
|
+
extend self
|
4
|
+
|
5
|
+
# Response headers
|
6
|
+
RATELIMIT_REMAINING = 'X-RateLimit-Remaining'.freeze
|
7
|
+
|
8
|
+
RATELIMIT_LIMIT = 'X-RateLimit-Limit'.freeze
|
9
|
+
|
10
|
+
CONTENT_TYPE = 'Content-Type'.freeze
|
11
|
+
|
12
|
+
CONTENT_LENGTH = 'content-length'.freeze
|
13
|
+
|
14
|
+
CACHE_CONTROL = 'cache-control'.freeze
|
15
|
+
|
16
|
+
ETAG = 'ETag'.freeze
|
17
|
+
|
18
|
+
SERVER = 'Server'.freeze
|
19
|
+
|
20
|
+
DATE = 'Date'.freeze
|
21
|
+
|
22
|
+
LOCATION = 'Location'.freeze
|
23
|
+
|
24
|
+
USER_AGENT = 'User-Agent'.freeze
|
25
|
+
|
26
|
+
ACCEPT = 'Accept'.freeze
|
27
|
+
|
28
|
+
ACCEPT_CHARSET = 'Accept-Charset'.freeze
|
29
|
+
|
30
|
+
end # Constants
|
31
|
+
end
|
data/lib/railties.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
module Request
|
3
|
+
class BasicAuth < Faraday::Middleware
|
4
|
+
dependency 'base64'
|
5
|
+
|
6
|
+
def call(env)
|
7
|
+
env[:request_headers].merge!('Authorization' => "Basic #{@auth}\"")
|
8
|
+
|
9
|
+
@app.call env
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(app, *args)
|
13
|
+
@app = app
|
14
|
+
credentials = ""
|
15
|
+
options = args.extract_options!
|
16
|
+
if options.has_key? :username
|
17
|
+
credentials = "#{options[:username]}:#{options[:password]}"
|
18
|
+
elsif options.has_key? :basic_auth
|
19
|
+
credentials = "#{options[:basic_auth]}"
|
20
|
+
end
|
21
|
+
@auth = Base64.encode64(credentials)
|
22
|
+
@auth.gsub!("\n", "")
|
23
|
+
end
|
24
|
+
end # BasicAuth
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Vertebrae
|
2
|
+
module Response
|
3
|
+
class RaiseError < Faraday::Response::Middleware
|
4
|
+
|
5
|
+
def on_complete(response)
|
6
|
+
status_code = response[:status].to_i
|
7
|
+
if (500...600).include? status_code
|
8
|
+
raise Exception.new(error_message(response))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def error_message(response)
|
13
|
+
"#{response[:method].to_s.upcase} #{response[:url].to_s}: #{response[:status]} \n\n #{response[:body] if response[:body]}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class NotFound < Exception ; end
|
18
|
+
end # Response::RaiseError
|
19
|
+
end
|
data/lib/vertebrae.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'constants'
|
2
|
+
require 'configuration'
|
3
|
+
require 'connection'
|
4
|
+
require 'authorization'
|
5
|
+
require 'api'
|
6
|
+
|
7
|
+
|
8
|
+
require 'active_support/all'
|
9
|
+
require 'vertebrae/railties' if defined? Rails
|
10
|
+
|
11
|
+
|
12
|
+
module Vertebrae
|
13
|
+
extend Configuration
|
14
|
+
|
15
|
+
|
16
|
+
def logger
|
17
|
+
@@logger ||= Logger.new(STDOUT)
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger=(logger)
|
21
|
+
@@logger = logger
|
22
|
+
end
|
23
|
+
|
24
|
+
# implement this in your api
|
25
|
+
#
|
26
|
+
def new(options = {}, &block)
|
27
|
+
raise "implement me!"
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(method, *args, &block)
|
31
|
+
return super unless new.respond_to?(method)
|
32
|
+
new.send(method, *args, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to?(method, include_private = false)
|
36
|
+
new.respond_to?(method, include_private) || super(method, include_private)
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
data/spec/api_spec.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vertebrae::API do
|
4
|
+
|
5
|
+
subject { described_class.new(options) }
|
6
|
+
|
7
|
+
it { described_class.included_modules.should include Vertebrae::Authorization }
|
8
|
+
it { described_class.included_modules.should include Vertebrae::Connection }
|
9
|
+
it { described_class.included_modules.should include Vertebrae::Request }
|
10
|
+
|
11
|
+
|
12
|
+
describe '#extract_id_from_location' do
|
13
|
+
let(:options) { {} }
|
14
|
+
it "should extract the id" do
|
15
|
+
subject.send(:extract_id_from_location, "https://roboticdogs.actionkit.com/rest/v1/importpage/1093/").should == "1093"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
context 'process_basic_auth' do
|
21
|
+
let(:options) { { :basic_auth => 'login:password' } }
|
22
|
+
|
23
|
+
its(:username) { should eq 'login' }
|
24
|
+
|
25
|
+
its(:password) { should eq 'password' }
|
26
|
+
|
27
|
+
its(:basic_auth) { should eq 'login:password' }
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'dummy' do
|
31
|
+
describe 'should delegate to the client class' do
|
32
|
+
specify{ Dummy.new.should respond_to(:api) }
|
33
|
+
specify{ Dummy.should respond_to(:api) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vertebrae::Authorization do
|
4
|
+
let(:options) { {} }
|
5
|
+
|
6
|
+
subject(:vb) { Dummy.new options }
|
7
|
+
|
8
|
+
after do
|
9
|
+
reset_authentication_for vb
|
10
|
+
end
|
11
|
+
|
12
|
+
context ".authenticated?" do
|
13
|
+
it { should respond_to(:authenticated?) }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "authentication" do
|
17
|
+
|
18
|
+
context 'username & password' do
|
19
|
+
let(:options) { { :username => 'vb', :password => 'pass' } }
|
20
|
+
|
21
|
+
it "should return hash with username & password params" do
|
22
|
+
vb.basic_auth.should == "#{options[:username]}:#{options[:password]}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end # authentication
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vertebrae::Configuration do
|
4
|
+
let(:klass) {
|
5
|
+
::Class.new do
|
6
|
+
extend Vertebrae::Configuration
|
7
|
+
end
|
8
|
+
}
|
9
|
+
|
10
|
+
subject { klass }
|
11
|
+
|
12
|
+
its(:adapter) { should == described_class::DEFAULT_ADAPTER }
|
13
|
+
|
14
|
+
its(:ssl) { should == described_class::DEFAULT_SSL }
|
15
|
+
|
16
|
+
its(:ssl) { should be_a Hash }
|
17
|
+
|
18
|
+
its(:user_agent) { should == described_class::DEFAULT_USER_AGENT }
|
19
|
+
|
20
|
+
its(:connection_options) { should be_a Hash }
|
21
|
+
|
22
|
+
its(:connection_options) { should be_empty }
|
23
|
+
|
24
|
+
its(:username) { should == described_class::DEFAULT_USERNAME }
|
25
|
+
|
26
|
+
its(:password) { should == described_class::DEFAULT_PASSWORD }
|
27
|
+
|
28
|
+
describe ".configure" do
|
29
|
+
it { should respond_to :configure }
|
30
|
+
|
31
|
+
described_class.keys.each do |key|
|
32
|
+
it "should set the #{key}" do
|
33
|
+
subject.configure do |config|
|
34
|
+
config.send("#{key}=", key)
|
35
|
+
subject.send(key).should == key
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/dummy/dummy.rb
ADDED
data/spec/logger_spec.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'logging' do
|
4
|
+
it "should have a logger" do
|
5
|
+
Dummy.respond_to?(:logger).should be_true
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should be able to log debug methods" do
|
9
|
+
Dummy.logger.respond_to?(:debug).should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be settable" do
|
13
|
+
Dummy.respond_to?(:logger=).should be_true
|
14
|
+
log = double()
|
15
|
+
Dummy.logger = log
|
16
|
+
Dummy.logger.should == log
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'vertebrae'
|
5
|
+
require 'dummy/dummy'
|
6
|
+
require 'dummy/client'
|
7
|
+
|
8
|
+
|
9
|
+
# Requires supporting files with custom matchers and macros, etc,
|
10
|
+
# in ./support/ and its subdirectories.
|
11
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def reset_authentication_for(object)
|
19
|
+
['username', 'password'].each do |item|
|
20
|
+
Vertebrae.send("#{item}=", nil)
|
21
|
+
object.send("#{item}=", nil)
|
22
|
+
end
|
23
|
+
end
|
data/vertebrae.gemspec
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "vertebrae"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Nathan Woodhull"]
|
12
|
+
s.date = "2013-07-12"
|
13
|
+
s.description = "A set of low level infrastructure and reusable code for building API clients"
|
14
|
+
s.email = "nathan@controlshiftlabs.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rspec",
|
22
|
+
".ruby-gemset",
|
23
|
+
".ruby-version",
|
24
|
+
"Gemfile",
|
25
|
+
"Gemfile.lock",
|
26
|
+
"LICENSE.txt",
|
27
|
+
"README.rdoc",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"lib/api.rb",
|
31
|
+
"lib/authorization.rb",
|
32
|
+
"lib/configuration.rb",
|
33
|
+
"lib/connection.rb",
|
34
|
+
"lib/constants.rb",
|
35
|
+
"lib/core_ext/array.rb",
|
36
|
+
"lib/railties.rb",
|
37
|
+
"lib/request/basic_auth.rb",
|
38
|
+
"lib/response/raise_error.rb",
|
39
|
+
"lib/vertebrae.rb",
|
40
|
+
"spec/api_spec.rb",
|
41
|
+
"spec/authorization_spec.rb",
|
42
|
+
"spec/configuration_spec.rb",
|
43
|
+
"spec/dummy/client.rb",
|
44
|
+
"spec/dummy/dummy.rb",
|
45
|
+
"spec/logger_spec.rb",
|
46
|
+
"spec/spec_helper.rb",
|
47
|
+
"vertebrae.gemspec"
|
48
|
+
]
|
49
|
+
s.homepage = "http://github.com/controlshift/vertebrae"
|
50
|
+
s.licenses = ["MIT"]
|
51
|
+
s.require_paths = ["lib"]
|
52
|
+
s.rubygems_version = "2.0.4"
|
53
|
+
s.summary = "API Client Infrastructure"
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
s.specification_version = 4
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
60
|
+
s.add_runtime_dependency(%q<faraday>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<faraday_middleware>, [">= 0"])
|
62
|
+
s.add_runtime_dependency(%q<hashie>, [">= 0"])
|
63
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
64
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
65
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
68
|
+
s.add_dependency(%q<faraday>, [">= 0"])
|
69
|
+
s.add_dependency(%q<faraday_middleware>, [">= 0"])
|
70
|
+
s.add_dependency(%q<hashie>, [">= 0"])
|
71
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
72
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
73
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
74
|
+
end
|
75
|
+
else
|
76
|
+
s.add_dependency(%q<activesupport>, [">= 0"])
|
77
|
+
s.add_dependency(%q<faraday>, [">= 0"])
|
78
|
+
s.add_dependency(%q<faraday_middleware>, [">= 0"])
|
79
|
+
s.add_dependency(%q<hashie>, [">= 0"])
|
80
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
81
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
82
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vertebrae
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Woodhull
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-12 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: faraday
|
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: faraday_middleware
|
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: hashie
|
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: rspec
|
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: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: jeweler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.8.4
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.8.4
|
111
|
+
description: A set of low level infrastructure and reusable code for building API
|
112
|
+
clients
|
113
|
+
email: nathan@controlshiftlabs.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files:
|
117
|
+
- LICENSE.txt
|
118
|
+
- README.rdoc
|
119
|
+
files:
|
120
|
+
- .document
|
121
|
+
- .rspec
|
122
|
+
- .ruby-gemset
|
123
|
+
- .ruby-version
|
124
|
+
- Gemfile
|
125
|
+
- Gemfile.lock
|
126
|
+
- LICENSE.txt
|
127
|
+
- README.rdoc
|
128
|
+
- Rakefile
|
129
|
+
- VERSION
|
130
|
+
- lib/api.rb
|
131
|
+
- lib/authorization.rb
|
132
|
+
- lib/configuration.rb
|
133
|
+
- lib/connection.rb
|
134
|
+
- lib/constants.rb
|
135
|
+
- lib/core_ext/array.rb
|
136
|
+
- lib/railties.rb
|
137
|
+
- lib/request/basic_auth.rb
|
138
|
+
- lib/response/raise_error.rb
|
139
|
+
- lib/vertebrae.rb
|
140
|
+
- spec/api_spec.rb
|
141
|
+
- spec/authorization_spec.rb
|
142
|
+
- spec/configuration_spec.rb
|
143
|
+
- spec/dummy/client.rb
|
144
|
+
- spec/dummy/dummy.rb
|
145
|
+
- spec/logger_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
- vertebrae.gemspec
|
148
|
+
homepage: http://github.com/controlshift/vertebrae
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata: {}
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - '>='
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 2.0.4
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: API Client Infrastructure
|
172
|
+
test_files: []
|