saddle 0.0.43 → 0.0.44

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  # Gems
9
9
  *.gem
10
+ Gemfile.lock
10
11
 
11
12
  # IDEs
12
13
  .idea
@@ -1,3 +1,14 @@
1
+ # 0.0.44
2
+ * Fixed a bug where child endpoints were being attached to the parent's class. This would
3
+ cause problems because the root node's class is always TraversalEndpoint, and would be shared
4
+ amongst concrete clients.
5
+
6
+ # 0.0.43
7
+ * Fixed a bug where non-string path elements were crashing
8
+
9
+ # 0.0.42
10
+ * Fixed a bug where nil actions resulted in a trailing /
11
+
1
12
  # 0.0.41
2
13
  * Cleanup of the path building chain makes nicer URLs
3
14
 
data/Gemfile CHANGED
@@ -1,10 +1,7 @@
1
1
  source 'https://rubygems.org'
2
+ gemspec
2
3
 
3
4
 
4
- gem 'activesupport', '>= 3.0', :require => 'active_support'
5
- gem 'faraday', '~> 0.8.7'
6
- gem 'faraday_middleware', '~> 0.9.0'
7
-
8
5
  group :test do
9
6
  gem 'rake'
10
7
  gem 'rspec', '~> 2.14.1'
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'erb'
4
+ require 'ostruct'
5
+
6
+ require 'active_support/core_ext/string'
7
+
8
+
9
+ # Creation options
10
+ # TODO: read via CLI
11
+ settings = {
12
+ service_name: 'Example',
13
+ author_name: 'Mike Lewis',
14
+ author_email: 'mike.lewis@airbnb.com',
15
+ github_account: 'airbnb',
16
+ }
17
+
18
+
19
+ # This holds the project settings and realizes templates
20
+ class ProjectGenerator
21
+ attr_reader :settings
22
+
23
+ # Expected settings:
24
+ # service_name
25
+ # author_name
26
+ # author_email
27
+ # github_account
28
+ def initialize(settings)
29
+ settings[:project_name] = "#{settings[:service_name].underscore}-client"
30
+ settings[:root_module] = settings[:service_name].split('_').map(&:capitalize).join('')
31
+ settings[:saddle_version] = Saddle::VERSION
32
+ @settings = OpenStruct.new(settings)
33
+
34
+ @template_dir = File.join(File.dirname(__FILE__), 'template')
35
+ @output_dir = '.'
36
+ end
37
+
38
+ # Transform a template file into the output directory
39
+ def transform_template(in_file, out_file=nil)
40
+ out_file = in_file if out_file.nil?
41
+ puts "Processing: #{out_file}"
42
+
43
+ # Ensure the directory is there
44
+ FileUtils.mkdir_p(File.dirname(out_file))
45
+ # Write the processed template
46
+ #puts File.read(File.join(@template_dir, in_file), 'r')
47
+ File.open(File.join(@output_dir, out_file), 'w') do |output|
48
+ output.puts(
49
+ ERB.new(
50
+ File.read(File.join(@template_dir, in_file))
51
+ ).result(
52
+ @settings.instance_eval { binding }
53
+ )
54
+ )
55
+ end
56
+ end
57
+ end
58
+
59
+ pg = ProjectGenerator.new(settings)
60
+ # /lib
61
+ # Create the contents of the gem directory in the correctly named directory
62
+ %w(
63
+ endpoints/status.rb
64
+ middleware/exception_raiser.rb
65
+ exceptions.rb
66
+ stub.rb
67
+ version.rb
68
+ ).each do |tmpl|
69
+ pg.transform_template("lib/saddle-client/#{tmpl}", "lib/#{pg.settings.project_name}/#{tmpl}")
70
+ end
71
+ pg.transform_template('lib/saddle-client.rb', "lib/#{pg.settings.project_name}.rb")
72
+ # /spec
73
+ pg.transform_template('spec/integration/status_spec.rb')
74
+ pg.transform_template('spec/middleware/exception_raiser_spec.rb')
75
+ pg.transform_template('spec/stub/stub_spec.rb')
76
+ pg.transform_template('spec/spec_helper.rb')
77
+ # /
78
+ pg.transform_template('.gitignore')
79
+ pg.transform_template('.rspec')
80
+ pg.transform_template('Gemfile')
81
+ pg.transform_template('LICENSE')
82
+ pg.transform_template('README.md')
83
+ pg.transform_template('saddle-client.gemspec', "#{pg.settings.project_name}.gemspec")
@@ -0,0 +1,20 @@
1
+ # Ignore temporary files
2
+ *.sw[op]
3
+ .DS_Store
4
+ *.log
5
+ *tmp
6
+ *~
7
+ *#
8
+
9
+ # RVM
10
+ .rvmrc
11
+
12
+ # Don't lock to specific dependencies. Design for incorporation into other projects.
13
+ Gemfile.lock
14
+
15
+ # Gems
16
+ *.gem
17
+
18
+ # IDEs
19
+ .idea
20
+ .project
@@ -0,0 +1,4 @@
1
+ --color
2
+ --backtrace
3
+ --require rspec/instafail
4
+ --format RSpec::Instafail
@@ -0,0 +1,14 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
5
+
6
+
7
+ group :test do
8
+ gem 'rspec', '~> 2.14.1'
9
+ gem 'rspec-instafail', '~> 0.2'
10
+ end
11
+
12
+ group :development, :test do
13
+ gem 'pry'
14
+ end
@@ -0,0 +1,19 @@
1
+ (c) <%= Time.now.year %>, <%= author_name %>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,27 @@
1
+ # <%= service_name %> client
2
+
3
+
4
+ ## Usage
5
+ ```ruby
6
+ client = <%= root_module %>::Client.create()
7
+ service_status = client.status.healthy?
8
+ ```
9
+
10
+
11
+ ## Testing
12
+
13
+ ### this project
14
+ * bundle exec rspec
15
+
16
+ ### from an including project
17
+ In your spec_helper.rb, include the following snippet.
18
+ ```ruby
19
+ <%= root_module %>::Client.stub!
20
+ ```
21
+ This will prevent `<%= project_name %>` from reaching out to live servers.
22
+ Instead, endpoints will return back [local stubbed data](lib/<%= project_name %>/stub.rb).
23
+
24
+
25
+ ## License
26
+ (c) <%= Time.now.year %>, <%= author_name %>
27
+ Released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'saddle'
4
+
5
+ require '<%= project_name %>/exceptions'
6
+ require '<%= project_name %>/middleware/exception_raiser'
7
+ require '<%= project_name %>/stub'
8
+ require '<%= project_name %>/version'
9
+
10
+
11
+
12
+ module <%= root_module %>
13
+
14
+ class Client < Saddle::Client
15
+ extend <%= root_module %>::Stub
16
+
17
+
18
+ # Place default client options here
19
+ # Saddle supports many more options than are listed below. See the documentation.
20
+ #def self.host
21
+ # 'example.org'
22
+ #end
23
+
24
+ #def self.use_ssl
25
+ # true
26
+ #end
27
+
28
+ #def self.num_retries
29
+ # 1
30
+ #end
31
+
32
+ #def self.timeout
33
+ # 5 # seconds
34
+ #end
35
+
36
+ # Raise exceptions, based upon request responses
37
+ add_middleware({
38
+ :klass => Middleware::ExceptionRaiser,
39
+ })
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'saddle/endpoint'
4
+
5
+ module <%= root_module %>
6
+ module Endpoints
7
+
8
+ class Status < Saddle::TraversalEndpoint
9
+
10
+ ABSOLUTE_PATH = ''
11
+
12
+ def healthy?
13
+ get('health') == 'OK'
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ ##
4
+ # Exceptions for using the <%= service_name %> client
5
+ # It is recommended that you handle these.
6
+ ##
7
+
8
+ module <%= root_module %>
9
+
10
+ class GenericException < StandardError; end
11
+
12
+ class TimeoutError < GenericException; end
13
+
14
+ # Some problems might take care of themselves if you try again later. Others won't.
15
+ class TemporaryError < GenericException; end # fire warnings on these
16
+ class PermanentError < GenericException; end # fire errors on these
17
+
18
+ # Implement derivative exception classes here that represent specific errors that the
19
+ # service can throw via status codes or response body
20
+
21
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'faraday'
4
+
5
+ require '<%= project_name %>/exceptions'
6
+
7
+
8
+
9
+ module <%= root_module %>
10
+ module Middleware
11
+
12
+ ## Raise beautiful exceptions
13
+ #
14
+ class ExceptionRaiser < Faraday::Middleware
15
+
16
+ ## For handling errors, the message that gets returned is of the following format:
17
+ # {:status => env[:status], :headers => env[:response_headers], :body => env[:body]}
18
+
19
+ def call(env)
20
+ begin
21
+ @app.call(env)
22
+ rescue Faraday::Error::ClientError => e
23
+ # This is our chance to reinterpret the response into a meaningful, client-specific
24
+ # exception that a consuming service can handle
25
+ exception = <%= root_module %>::GenericException
26
+
27
+ raise exception, e.response
28
+ rescue Saddle::TimeoutError => e
29
+ raise <%= root_module %>::TimeoutError, e.response
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require '<%= project_name %>/endpoints/status'
4
+
5
+ # This allows us to stub out live calls when testing from calling projects
6
+
7
+ module <%= root_module %>
8
+ module Stub
9
+
10
+ # Setup stubbing for all endpoints
11
+ def stub!
12
+ <%= root_module %>::Endpoints::Status.any_instance.stub(:healthy?).and_return(
13
+ Stub::Data::TEST_STATUS_HEALTHY_RESPONSE
14
+ )
15
+ end
16
+
17
+ # Test data for stubs to return
18
+ module Data
19
+
20
+ TEST_STATUS_HEALTHY_RESPONSE = 'OK'.freeze
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module <%= root_module %>
4
+ VERSION = '0.0.0'
5
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/<%= project_name %>/version', __FILE__)
4
+
5
+ lib = File.expand_path('../lib', __FILE__)
6
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
+
8
+ Gem::Specification.new do |s|
9
+ s.name = '<%= project_name %>'
10
+ s.version = ::<%= root_module %>::VERSION
11
+ s.authors = ['<%= author_name %>']
12
+ s.email = ['<%= author_email %>']
13
+ s.description = %q{<%= service_name %> client}
14
+ s.summary = %q{
15
+ This is a <%= service_name %> client implemented on Saddle
16
+ }
17
+ s.homepage = 'https://github.com/<%= github_account %>/<%= project_name %>'
18
+ s.license = 'MIT'
19
+
20
+ s.require_path = 'lib'
21
+ s.files = `git ls-files`.split($\)
22
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
24
+
25
+ s.add_dependency 'saddle', '~> <%= saddle_version %>'
26
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ ###
7
+ # NOTE: This spec will actually hit live servers
8
+ ###
9
+
10
+ describe '<%= root_module %>::Endpoints::User' do
11
+ context "Test integration of status endpoints" do
12
+
13
+ let(:client) { <%= root_module %>::Client.create() }
14
+
15
+ it 'should get self profile' do
16
+ client.status.healthy?.should be_true
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+ describe <%= root_module %>::Middleware::ExceptionRaiser do
7
+
8
+ describe "Test raising various exceptions using stubs" do
9
+
10
+ let(:stubs) { Faraday::Adapter::Test::Stubs.new }
11
+ let(:client) { <%= root_module %>::Client.create(:stubs => stubs) }
12
+
13
+
14
+ it 'should detect a service error' do
15
+ stubs.get('/') { [ 500, {}, { 'status' => 'error' } ] }
16
+ expect { client.requester.get('') }.to raise_error(<%= root_module %>::GenericException)
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,3 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require '<%= project_name %>'
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+
6
+
7
+ describe <%= root_module %>::Stub do
8
+ context 'stubbing out calls' do
9
+
10
+ let(:client) { <%= root_module %>::Client.create }
11
+
12
+ before :each do
13
+ <%= root_module %>::Client.stub!
14
+ end
15
+
16
+ describe 'returns test data' do
17
+ it 'for client.status.healthy?' do
18
+ client.status.healthy?.should be_true
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -68,7 +68,7 @@ module Saddle
68
68
  # Attach the endpoint as an instance variable and method
69
69
  method_name ||= endpoint_class.name.demodulize.underscore
70
70
  self.instance_variable_set("@#{method_name}", endpoint_instance)
71
- self.class.class_eval { define_method(method_name) { endpoint_instance } }
71
+ self.define_singleton_method(method_name.to_s) { endpoint_instance }
72
72
  endpoint_instance
73
73
  end
74
74
 
@@ -132,6 +132,9 @@ module Saddle
132
132
  # traversal tree.
133
133
  class TraversalEndpoint < BaseEndpoint; end
134
134
 
135
+ # This is a special case endpoint for the root node.
136
+ class RootEndpoint < TraversalEndpoint; end
137
+
135
138
 
136
139
  # This endpoint is used for constructing resource-style endpoints. This
137
140
  # means it will NOT be automatically added into the traversal tree.
@@ -44,11 +44,11 @@ module Saddle
44
44
  root_node_class = self.implementation_module::RootEndpoint
45
45
  else
46
46
  # 'root_endpoint.rb' doesn't exist, so create a dummy endpoint
47
- root_node_class = Saddle::TraversalEndpoint
47
+ root_node_class = Saddle::RootEndpoint
48
48
  end
49
49
  else
50
50
  # we don't even have an implementation root, so create a dummy endpoint
51
- root_node_class = Saddle::TraversalEndpoint
51
+ root_node_class = Saddle::RootEndpoint
52
52
  end
53
53
  root_node_class.new(requester, nil, self)
54
54
  end
@@ -1,3 +1,3 @@
1
1
  module Saddle
2
- VERSION = '0.0.43'
2
+ VERSION = '0.0.44'
3
3
  end
@@ -19,8 +19,8 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.require_path = 'lib'
21
21
  s.files = `git ls-files`.split($\)
22
- s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
23
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
22
+ s.executables = ['saddle']
23
+ s.test_files = s.files.grep(%r{^(spec)/})
24
24
 
25
25
  s.add_dependency 'activesupport', '>= 3.0'
26
26
  s.add_dependency 'faraday', '~> 0.8.7'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.43
4
+ version: 0.0.44
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-15 00:00:00.000000000 Z
12
+ date: 2013-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -61,7 +61,8 @@ dependencies:
61
61
  version: 0.9.0
62
62
  description: Makes writing API clients as easy as giving high fives
63
63
  email: mike.lewis@airbnb.com
64
- executables: []
64
+ executables:
65
+ - saddle
65
66
  extensions: []
66
67
  extra_rdoc_files: []
67
68
  files:
@@ -70,9 +71,25 @@ files:
70
71
  - .travis.yml
71
72
  - CHANGELOG.md
72
73
  - Gemfile
73
- - Gemfile.lock
74
74
  - LICENSE
75
75
  - README.md
76
+ - bin/saddle
77
+ - bin/template/.gitignore
78
+ - bin/template/.rspec
79
+ - bin/template/Gemfile
80
+ - bin/template/LICENSE
81
+ - bin/template/README.md
82
+ - bin/template/lib/saddle-client.rb
83
+ - bin/template/lib/saddle-client/endpoints/status.rb
84
+ - bin/template/lib/saddle-client/exceptions.rb
85
+ - bin/template/lib/saddle-client/middleware/exception_raiser.rb
86
+ - bin/template/lib/saddle-client/stub.rb
87
+ - bin/template/lib/saddle-client/version.rb
88
+ - bin/template/saddle-client.gemspec
89
+ - bin/template/spec/integration/status_spec.rb
90
+ - bin/template/spec/middleware/exception_raiser_spec.rb
91
+ - bin/template/spec/spec_helper.rb
92
+ - bin/template/spec/stub/stub_spec.rb
76
93
  - lib/saddle.rb
77
94
  - lib/saddle/client_attributes.rb
78
95
  - lib/saddle/endpoint.rb
@@ -1,54 +0,0 @@
1
- GEM
2
- remote: https://rubygems.org/
3
- specs:
4
- activesupport (3.2.13)
5
- i18n (= 0.6.1)
6
- multi_json (~> 1.0)
7
- airbrake (3.1.12)
8
- activesupport
9
- builder
10
- json
11
- builder (3.2.0)
12
- coderay (1.0.9)
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
- i18n (0.6.1)
19
- json (1.7.7)
20
- method_source (0.8.1)
21
- multi_json (1.7.3)
22
- multipart-post (1.2.0)
23
- pry (0.9.12.2)
24
- coderay (~> 1.0.5)
25
- method_source (~> 0.8)
26
- slop (~> 3.4)
27
- rake (10.1.0)
28
- rspec (2.14.1)
29
- rspec-core (~> 2.14.0)
30
- rspec-expectations (~> 2.14.0)
31
- rspec-mocks (~> 2.14.0)
32
- rspec-core (2.14.2)
33
- rspec-expectations (2.14.0)
34
- diff-lcs (>= 1.1.3, < 2.0)
35
- rspec-instafail (0.2.4)
36
- rspec-mocks (2.14.1)
37
- simple_oauth (0.2.0)
38
- slop (3.4.5)
39
- statsd-ruby (1.2.0)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- activesupport (>= 3.0)
46
- airbrake
47
- faraday (~> 0.8.7)
48
- faraday_middleware (~> 0.9.0)
49
- pry
50
- rake
51
- rspec (~> 2.14.1)
52
- rspec-instafail (~> 0.2)
53
- simple_oauth (~> 0.2.0)
54
- statsd-ruby