vertebrae 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
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
@@ -0,0 +1,5 @@
1
+ class Array
2
+ def extract_options!
3
+ last.is_a?(::Hash) ? pop : {}
4
+ end
5
+ end
data/lib/railties.rb ADDED
@@ -0,0 +1,7 @@
1
+ module Vertebrae
2
+ class Railties < ::Rails::Railtie
3
+ initializer 'Rails logger' do
4
+ Vertebrae.logger = Rails.logger
5
+ end
6
+ end
7
+ end
@@ -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
@@ -0,0 +1,7 @@
1
+ module Dummy
2
+ class Client < Vertebrae::API
3
+ def api(options={}, &block)
4
+ @api ||= Vertebrae::API.new(current_options.merge(options), &block)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Dummy
2
+ extend Vertebrae
3
+ class << self
4
+ def new(options = {}, &block)
5
+ Dummy::Client.new(options, &block)
6
+ end
7
+ end
8
+ end
@@ -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
@@ -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: []