hovercraft 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -1,5 +1,6 @@
1
1
  require 'hovercraft/loader'
2
- require 'hovercraft/actions'
2
+ require 'hovercraft/routes'
3
+ require 'hovercraft/helpers'
3
4
  require 'sinatra/base'
4
5
  require 'rack/contrib'
5
6
  require 'forwardable'
@@ -22,7 +23,8 @@ module Hovercraft
22
23
  end
23
24
 
24
25
  def configure(application)
25
- application.register(Hovercraft::Actions)
26
+ application.register(Hovercraft::Helpers)
27
+ application.register(Hovercraft::Routes)
26
28
  application.use(Rack::PostBodyContentTypeParser)
27
29
  application
28
30
  end
@@ -0,0 +1,38 @@
1
+ module Hovercraft
2
+ module Helpers
3
+ def self.registered(application)
4
+ application.helpers(Hovercraft::Helpers)
5
+ end
6
+
7
+ def respond_with(content)
8
+ if content.respond_to?(format_method_name)
9
+ content.send(format_method_name)
10
+ else
11
+ fail "Serialization method not supported: #{format_method_name}"
12
+ end
13
+ end
14
+
15
+ def format_method_name
16
+ "to_#{format}"
17
+ end
18
+
19
+ def format
20
+ params[:format] ||
21
+ preferred_type ||
22
+ default_format
23
+ end
24
+
25
+ def preferred_type
26
+ case request.preferred_type
27
+ when /.*\/json/ then :json
28
+ when /.*\/xml/ then :xml
29
+ when /.*\/\*/ then default_format
30
+ else fail "Unknown media type: %p" % request.preferred_type
31
+ end
32
+ end
33
+
34
+ def default_format
35
+ :json
36
+ end
37
+ end
38
+ end
@@ -1,46 +1,44 @@
1
- require 'sinatra/base'
2
-
3
1
  module Hovercraft
4
- module Actions
2
+ module Routes
5
3
  def generate_index(model_class, model_name, plural_model_name)
6
- get("/#{plural_model_name}.:format") do
4
+ get(%r{^/#{plural_model_name}(\.(?<format>[^\./?#]+))?$}) do
7
5
  model_instances = model_class.all
8
6
  status 200
9
- model_instances.to_json
7
+ respond_with model_instances
10
8
  end
11
9
  end
12
10
 
13
11
  def generate_create(model_class, model_name, plural_model_name)
14
- post("/#{plural_model_name}.:format") do
12
+ post(%r{^/#{plural_model_name}(\.(?<format>[^\./?#]+))?$}) do
15
13
  model_instance = model_class.create(params[model_name.to_sym])
16
14
  status model_instance.valid? ? 201 : 400
17
- model_instance.to_json
15
+ respond_with model_instance
18
16
  end
19
17
  end
20
18
 
21
19
  def generate_show(model_class, model_name, plural_model_name)
22
- get("/#{plural_model_name}/:id.:format") do
20
+ get(%r{^/#{plural_model_name}/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}) do
23
21
  model_instance = model_class.find(params[:id])
24
22
  status 200
25
- model_instance.to_json
23
+ respond_with model_instance
26
24
  end
27
25
  end
28
26
 
29
27
  def generate_update(model_class, model_name, plural_model_name)
30
- put("/#{plural_model_name}/:id.:format") do
28
+ put(%r{^/#{plural_model_name}/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}) do
31
29
  model_instance = model_class.find(params[:id])
32
30
  model_instance.update_attributes(params[model_name.to_sym])
33
31
  status model_instance.valid? ? 204 : 400
34
- model_instance.to_json
32
+ respond_with model_instance
35
33
  end
36
34
  end
37
35
 
38
36
  def generate_destroy(model_class, model_name, plural_model_name)
39
- delete("/#{plural_model_name}/:id.:format") do
37
+ delete(%r{^/#{plural_model_name}/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}) do
40
38
  model_instance = model_class.find(params[:id])
41
39
  model_instance.destroy
42
40
  status 204
43
- model_instance.to_json
41
+ respond_with model_instance
44
42
  end
45
43
  end
46
44
  end
@@ -1,3 +1,3 @@
1
1
  module Hovercraft
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -33,8 +33,14 @@ describe Hovercraft::Builder do
33
33
  describe '#configure' do
34
34
  let(:application) { stub(register: nil, use: nil) }
35
35
 
36
+ it 'registers the helper methods' do
37
+ application.should_receive(:register).with(Hovercraft::Helpers)
38
+
39
+ subject.configure(application)
40
+ end
41
+
36
42
  it 'registers the methods to generate actions' do
37
- application.should_receive(:register).with(Hovercraft::Actions)
43
+ application.should_receive(:register).with(Hovercraft::Routes)
38
44
 
39
45
  subject.configure(application)
40
46
  end
@@ -0,0 +1,86 @@
1
+ require 'hovercraft/helpers'
2
+
3
+ describe Hovercraft::Helpers do
4
+ subject { Class.new { extend Hovercraft::Helpers } }
5
+ let(:model_to_json) { stub }
6
+ let(:model) { stub(to_json: model_to_json) }
7
+
8
+ describe '.registered' do
9
+ let(:application) { stub }
10
+
11
+ it 'includes the helpers in the application' do
12
+ application.should_receive(:helpers).with(described_class)
13
+
14
+ Hovercraft::Helpers.registered(application)
15
+ end
16
+ end
17
+
18
+ describe '#respond_with' do
19
+ it 'serializes the content to the preferred format' do
20
+ subject.stub(format: :json)
21
+
22
+ subject.respond_with(model).should == model_to_json
23
+ end
24
+
25
+ it 'fails if the preferred format is not supported' do
26
+ subject.stub(format: :xml)
27
+
28
+ lambda { subject.respond_with(model) }.should raise_error
29
+ end
30
+ end
31
+
32
+ describe '#format' do
33
+ let(:format_param) { stub }
34
+ let(:preferred_type) { stub }
35
+ let(:default_format) { stub }
36
+
37
+ before do
38
+ subject.stub(
39
+ params: { format: nil },
40
+ preferred_type: nil,
41
+ default_format: nil
42
+ )
43
+ end
44
+
45
+ it 'defaults to the format param' do
46
+ subject.stub(params: { format: format_param })
47
+ subject.format.should == format_param
48
+ end
49
+
50
+ it 'falls back on the preferred_type' do
51
+ subject.stub(preferred_type: preferred_type)
52
+ subject.format.should == preferred_type
53
+ end
54
+
55
+ it 'uses the default format as a worst case' do
56
+ subject.stub(default_format: default_format)
57
+ subject.format.should == default_format
58
+ end
59
+ end
60
+
61
+ describe '#preferred_type' do
62
+ let(:default_format) { stub }
63
+
64
+ before { subject.stub(default_format: default_format) }
65
+
66
+ it 'checks for json' do
67
+ subject.stub_chain(:request, :preferred_type) { 'application/json' }
68
+ subject.preferred_type.should == :json
69
+ end
70
+
71
+ it 'checks for xml' do
72
+ subject.stub_chain(:request, :preferred_type) { 'application/xml' }
73
+ subject.preferred_type.should == :xml
74
+ end
75
+
76
+ it 'defaults to json if any format is allowed' do
77
+ subject.stub_chain(:request, :preferred_type) { '*/*' }
78
+ subject.preferred_type.should == default_format
79
+ end
80
+
81
+ it 'fails if the acceptable type is unknown' do
82
+ subject.stub_chain(:request, :preferred_type) { 'unknown/type' }
83
+ lambda { subject.preferred_type.should }.should raise_error
84
+ end
85
+ end
86
+ end
@@ -1,7 +1,9 @@
1
- require 'hovercraft/actions'
1
+ require 'hovercraft/routes'
2
+ require 'hovercraft/helpers'
3
+ require 'sinatra'
2
4
  require 'rack/test'
3
5
 
4
- describe Hovercraft::Actions do
6
+ describe Hovercraft::Routes do
5
7
  include Rack::Test::Methods
6
8
 
7
9
  let(:application) { Sinatra.new }
@@ -50,7 +52,8 @@ describe Hovercraft::Actions do
50
52
  alias :app :application
51
53
 
52
54
  before do
53
- application.register(Hovercraft::Actions)
55
+ application.register(Hovercraft::Helpers)
56
+ application.register(Hovercraft::Routes)
54
57
 
55
58
  model_class.stub(all: models, create: model, find: model)
56
59
  end
@@ -61,7 +64,7 @@ describe Hovercraft::Actions do
61
64
  end
62
65
 
63
66
  it 'generates a GET collection route' do
64
- application.routes['GET'][0][0].should == %r{^/employees(?:\.|%2E)([^/?#]+)$}
67
+ application.routes['GET'][0][0].should == %r{^/employees(\.(?<format>[^\./?#]+))?$}
65
68
  application.routes['GET'][0][1].should == ['format']
66
69
  end
67
70
 
@@ -78,7 +81,7 @@ describe Hovercraft::Actions do
78
81
  end
79
82
 
80
83
  it 'generates a POST collection route' do
81
- application.routes['POST'][0][0].should == %r{^/employees(?:\.|%2E)([^/?#]+)$}
84
+ application.routes['POST'][0][0].should == %r{^/employees(\.(?<format>[^\./?#]+))?$}
82
85
  application.routes['POST'][0][1].should == ['format']
83
86
  end
84
87
 
@@ -103,7 +106,7 @@ describe Hovercraft::Actions do
103
106
  end
104
107
 
105
108
  it 'generates a GET member route' do
106
- application.routes['GET'][0][0].should == %r{^/employees/([^/?#]+)(?:\.|%2E)([^/?#]+)$}
109
+ application.routes['GET'][0][0].should == %r{^/employees/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}
107
110
  application.routes['GET'][0][1].should == ['id', 'format']
108
111
  end
109
112
 
@@ -120,7 +123,7 @@ describe Hovercraft::Actions do
120
123
  end
121
124
 
122
125
  it 'generates a PUT member route' do
123
- application.routes['PUT'][0][0].should == %r{^/employees/([^/?#]+)(?:\.|%2E)([^/?#]+)$}
126
+ application.routes['PUT'][0][0].should == %r{^/employees/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}
124
127
  application.routes['PUT'][0][1].should == ['id', 'format']
125
128
  end
126
129
 
@@ -145,7 +148,7 @@ describe Hovercraft::Actions do
145
148
  end
146
149
 
147
150
  it 'generates a DELETE member route' do
148
- application.routes['DELETE'][0][0].should == %r{^/employees/([^/?#]+)(?:\.|%2E)([^/?#]+)$}
151
+ application.routes['DELETE'][0][0].should == %r{^/employees/(?<id>[^\./?#]+)(\.(?<format>[^\./?#]+))?$}
149
152
  application.routes['DELETE'][0][1].should == ['id', 'format']
150
153
  end
151
154
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hovercraft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
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: 2012-07-11 00:00:00.000000000 Z
12
+ date: 2012-07-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra-activerecord
@@ -115,6 +115,7 @@ extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
117
  - .gitignore
118
+ - .rspec
118
119
  - .travis.yml
119
120
  - Gemfile
120
121
  - LICENSE
@@ -122,16 +123,18 @@ files:
122
123
  - Rakefile
123
124
  - hovercraft.gemspec
124
125
  - lib/hovercraft.rb
125
- - lib/hovercraft/actions.rb
126
126
  - lib/hovercraft/builder.rb
127
127
  - lib/hovercraft/caller.rb
128
+ - lib/hovercraft/helpers.rb
128
129
  - lib/hovercraft/loader.rb
130
+ - lib/hovercraft/routes.rb
129
131
  - lib/hovercraft/server.rb
130
132
  - lib/hovercraft/version.rb
131
- - spec/hovercraft/actions_spec.rb
132
133
  - spec/hovercraft/builder_spec.rb
133
134
  - spec/hovercraft/caller_spec.rb
135
+ - spec/hovercraft/helpers_spec.rb
134
136
  - spec/hovercraft/loader_spec.rb
137
+ - spec/hovercraft/routes_spec.rb
135
138
  - spec/hovercraft/server_spec.rb
136
139
  homepage: ''
137
140
  licenses: []
@@ -147,7 +150,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
147
150
  version: '0'
148
151
  segments:
149
152
  - 0
150
- hash: 1562352661766896187
153
+ hash: -800613418121454242
151
154
  required_rubygems_version: !ruby/object:Gem::Requirement
152
155
  none: false
153
156
  requirements:
@@ -156,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
159
  version: '0'
157
160
  segments:
158
161
  - 0
159
- hash: 1562352661766896187
162
+ hash: -800613418121454242
160
163
  requirements: []
161
164
  rubyforge_project:
162
165
  rubygems_version: 1.8.23
@@ -167,8 +170,9 @@ summary: There's a lot of boiler plate code that goes into creating an API so wh
167
170
  directory and call the server from the rackup file and you have yourself a perfect
168
171
  API.
169
172
  test_files:
170
- - spec/hovercraft/actions_spec.rb
171
173
  - spec/hovercraft/builder_spec.rb
172
174
  - spec/hovercraft/caller_spec.rb
175
+ - spec/hovercraft/helpers_spec.rb
173
176
  - spec/hovercraft/loader_spec.rb
177
+ - spec/hovercraft/routes_spec.rb
174
178
  - spec/hovercraft/server_spec.rb