apiculture 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/Gemfile +1 -1
- data/README.md +42 -34
- data/apiculture.gemspec +7 -6
- data/lib/apiculture/method_documentation.rb +34 -22
- data/lib/apiculture/version.rb +1 -1
- data/lib/apiculture.rb +16 -7
- data/spec/apiculture/app_documentation_spec.rb +5 -0
- data/spec/apiculture/method_documentation_spec.rb +18 -0
- data/spec/apiculture_spec.rb +87 -0
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 52cb357c6a73e99a64db5e12a108b7a73cd5afd8
|
|
4
|
+
data.tar.gz: 7c03623922d85c6947ca1ca4026d3b29e584fe4f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9c97d38dab84b5c6d4cda3d2fb04c30f1c4c3ea8f7ff6cdd6432f5656ddc6523a7a95aaa4919324f28839669e8aa3c7bea0e65c0c73ab274573625805c1bd3e5
|
|
7
|
+
data.tar.gz: 8d289be328fbc019a55dab97317c219d0ddb48e181078bc446d5da4d13b8b6de2accf688d03a6965bd8733928efb71f633916ad60a4f6d9900f38c375e0ed26d
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A little toolkit for building RESTful API backends on top of Sinatra.
|
|
4
4
|
|
|
5
|
+
[](https://travis-ci.org/WeTransfer/apiculture)
|
|
6
|
+
|
|
5
7
|
## Ideas
|
|
6
8
|
|
|
7
9
|
A simple API definition DSL with simple premises:
|
|
@@ -15,54 +17,60 @@ A simple API definition DSL with simple premises:
|
|
|
15
17
|
|
|
16
18
|
## A taste of honey
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
20
|
+
```ruby
|
|
21
|
+
class Api::V2 < Sinatra::Base
|
|
22
|
+
|
|
23
|
+
use Rack::Parser, :content_types => {
|
|
24
|
+
'application/json' => JSON.method(:load).to_proc
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
extend Apiculture
|
|
28
|
+
|
|
29
|
+
desc 'Create a Contact'
|
|
30
|
+
required_param :name, 'Name of the person', String
|
|
31
|
+
param :email, 'Email address of the person', String
|
|
32
|
+
param :phone, 'Phone number', String, cast: ->(v) { v.scan(/\d/).flatten.join }
|
|
33
|
+
param :notes, 'Notes about this person', String
|
|
34
|
+
api_method :post, '/contacts' do
|
|
35
|
+
# anything allowed within Sinatra actions is allowed here, and
|
|
36
|
+
# works exactly the same - but we suggest using Actions instead.
|
|
37
|
+
action_result CreateContact # uses Api::V2::CreateContact
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc 'Fetch a Contact'
|
|
41
|
+
route_param :id, 'ID of the person'
|
|
42
|
+
responds_with 200, 'Contact data', {name: 'John Appleseed', id: "ac19...fefg"}
|
|
43
|
+
api_method :get, '/contacts/:id' do | person_id |
|
|
44
|
+
json Person.find(person_id).to_json
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
```
|
|
44
48
|
|
|
45
49
|
## Generating documentation
|
|
46
50
|
|
|
47
51
|
For the aforementioned example:
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
```ruby
|
|
54
|
+
File.open('API.html', 'w') do |f|
|
|
55
|
+
f << Api::V2.api_documentation.to_html
|
|
56
|
+
end
|
|
57
|
+
```
|
|
52
58
|
|
|
53
59
|
or to get it in Markdown:
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
```ruby
|
|
62
|
+
File.open('API.md', 'w') do |f|
|
|
63
|
+
f << Api::V2.api_documentation.to_markdown
|
|
64
|
+
end
|
|
65
|
+
```
|
|
58
66
|
|
|
59
67
|
## Running the tests
|
|
60
68
|
|
|
61
|
-
$bundle exec rspec
|
|
69
|
+
$ bundle exec rspec
|
|
62
70
|
|
|
63
71
|
If you want to also examine the HTML documentation that gets built during the test, set `SHOW_TEST_DOC` in env:
|
|
64
72
|
|
|
65
|
-
$SHOW_TEST_DOC=yes bundle exec rspec
|
|
73
|
+
$ SHOW_TEST_DOC=yes bundle exec rspec
|
|
66
74
|
|
|
67
75
|
Note that this requires presence of the `open` commandline utility (should be available on both OSX and Linux).
|
|
68
76
|
|
data/apiculture.gemspec
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: apiculture 0.0.
|
|
5
|
+
# stub: apiculture 0.0.14 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "apiculture"
|
|
9
|
-
s.version = "0.0.
|
|
9
|
+
s.version = "0.0.14"
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib"]
|
|
13
13
|
s.authors = ["Julik Tarkhanov", "WeTransfer"]
|
|
14
|
-
s.date = "
|
|
14
|
+
s.date = "2016-06-01"
|
|
15
15
|
s.description = "A toolkit for building REST APIs on top of Sinatra"
|
|
16
16
|
s.email = "me@julik.nl"
|
|
17
17
|
s.extra_rdoc_files = [
|
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
"README.md"
|
|
20
20
|
]
|
|
21
21
|
s.files = [
|
|
22
|
+
".travis.yml",
|
|
22
23
|
"Gemfile",
|
|
23
24
|
"LICENSE.txt",
|
|
24
25
|
"README.md",
|
|
@@ -58,7 +59,7 @@ Gem::Specification.new do |s|
|
|
|
58
59
|
s.add_development_dependency(%q<rspec>, ["< 3.2", "~> 3.1"])
|
|
59
60
|
s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
|
|
60
61
|
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
|
61
|
-
s.add_development_dependency(%q<jeweler>, ["~> 2
|
|
62
|
+
s.add_development_dependency(%q<jeweler>, ["~> 2"])
|
|
62
63
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
|
63
64
|
else
|
|
64
65
|
s.add_dependency(%q<sinatra>, ["~> 1.4"])
|
|
@@ -70,7 +71,7 @@ Gem::Specification.new do |s|
|
|
|
70
71
|
s.add_dependency(%q<rspec>, ["< 3.2", "~> 3.1"])
|
|
71
72
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
|
72
73
|
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
|
73
|
-
s.add_dependency(%q<jeweler>, ["~> 2
|
|
74
|
+
s.add_dependency(%q<jeweler>, ["~> 2"])
|
|
74
75
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
|
75
76
|
end
|
|
76
77
|
else
|
|
@@ -83,7 +84,7 @@ Gem::Specification.new do |s|
|
|
|
83
84
|
s.add_dependency(%q<rspec>, ["< 3.2", "~> 3.1"])
|
|
84
85
|
s.add_dependency(%q<rdoc>, ["~> 3.12"])
|
|
85
86
|
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
|
86
|
-
s.add_dependency(%q<jeweler>, ["~> 2
|
|
87
|
+
s.add_dependency(%q<jeweler>, ["~> 2"])
|
|
87
88
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
|
88
89
|
end
|
|
89
90
|
end
|
|
@@ -11,7 +11,7 @@ class Apiculture::MethodDocumentation
|
|
|
11
11
|
@definition = action_definition
|
|
12
12
|
@mountpoint = mountpoint
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
# Compose a Markdown definition of the action
|
|
16
16
|
def to_markdown
|
|
17
17
|
m = MDBuf.new
|
|
@@ -20,42 +20,42 @@ class Apiculture::MethodDocumentation
|
|
|
20
20
|
m << route_parameters_table
|
|
21
21
|
m << request_parameters_table
|
|
22
22
|
m << possible_responses_table
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
m.to_s
|
|
25
25
|
end
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
# Compose an HTML string by converting the result of +to_markdown+
|
|
28
28
|
def to_html_fragment
|
|
29
29
|
require 'rdiscount'
|
|
30
30
|
RDiscount.new(to_markdown).to_html
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
private
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
class StringBuf #:nodoc:
|
|
36
36
|
def initialize; @blocks = []; end
|
|
37
37
|
def <<(block); @blocks << block.to_s; self; end
|
|
38
38
|
def to_s; @blocks.join; end
|
|
39
39
|
end
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
class MDBuf < StringBuf #:nodoc:
|
|
42
42
|
def to_s; @blocks.join("\n\n"); end
|
|
43
43
|
end
|
|
44
|
-
|
|
45
|
-
def
|
|
44
|
+
|
|
45
|
+
def _route_parameters_table
|
|
46
46
|
return '' unless @definition.defines_route_params?
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
m = MDBuf.new
|
|
49
49
|
b = StringBuf.new
|
|
50
50
|
m << '### URL parameters'
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
html = Builder::XmlMarkup.new(:target => b)
|
|
53
53
|
html.table(class: 'apiculture-table') do
|
|
54
54
|
html.tr do
|
|
55
55
|
html.th 'Name'
|
|
56
56
|
html.th 'Description'
|
|
57
57
|
end
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
@definition.route_parameters.each do | param |
|
|
60
60
|
html.tr do
|
|
61
61
|
html.td { html.tt(':%s' % param.name) }
|
|
@@ -65,7 +65,7 @@ class Apiculture::MethodDocumentation
|
|
|
65
65
|
end
|
|
66
66
|
m << b.to_s
|
|
67
67
|
end
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
def body_example(for_response_definition)
|
|
70
70
|
if for_response_definition.no_body?
|
|
71
71
|
'(empty)'
|
|
@@ -73,14 +73,14 @@ class Apiculture::MethodDocumentation
|
|
|
73
73
|
JSON.pretty_generate(for_response_definition.jsonable_object_example)
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
def possible_responses_table
|
|
78
78
|
return '' unless @definition.defines_responses?
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
m = MDBuf.new
|
|
81
81
|
b = StringBuf.new
|
|
82
82
|
m << '### Possible responses'
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
html = Builder::XmlMarkup.new(:target => b)
|
|
85
85
|
html.table(class: 'apiculture-table') do
|
|
86
86
|
html.tr do
|
|
@@ -88,7 +88,7 @@ class Apiculture::MethodDocumentation
|
|
|
88
88
|
html.th('What happened')
|
|
89
89
|
html.th('Example response body')
|
|
90
90
|
end
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
@definition.responses.each do | resp |
|
|
93
93
|
html.tr do
|
|
94
94
|
html.td { html.b(resp.http_status_code) }
|
|
@@ -97,15 +97,27 @@ class Apiculture::MethodDocumentation
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
m << b.to_s
|
|
102
102
|
end
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
def request_parameters_table
|
|
105
105
|
return '' unless @definition.defines_request_params?
|
|
106
|
-
|
|
107
106
|
m = MDBuf.new
|
|
108
107
|
m << '### Request parameters'
|
|
108
|
+
m << parameters_table(@definition.parameters).to_s
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def route_parameters_table
|
|
112
|
+
return '' unless @definition.defines_route_params?
|
|
113
|
+
m = MDBuf.new
|
|
114
|
+
m << '### URL parameters'
|
|
115
|
+
m << parameters_table(@definition.route_parameters).to_s
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
def parameters_table(parameters)
|
|
109
121
|
b = StringBuf.new
|
|
110
122
|
html = Builder::XmlMarkup.new(:target => b)
|
|
111
123
|
html.table(class: 'apiculture-table') do
|
|
@@ -115,8 +127,8 @@ class Apiculture::MethodDocumentation
|
|
|
115
127
|
html.th 'Type after cast'
|
|
116
128
|
html.th 'Description'
|
|
117
129
|
end
|
|
118
|
-
|
|
119
|
-
|
|
130
|
+
|
|
131
|
+
parameters.each do | param |
|
|
120
132
|
html.tr do
|
|
121
133
|
html.td { html.tt(param.name.to_s) }
|
|
122
134
|
html.td(param.required ? 'Yes' : 'No')
|
|
@@ -125,6 +137,6 @@ class Apiculture::MethodDocumentation
|
|
|
125
137
|
end
|
|
126
138
|
end
|
|
127
139
|
end
|
|
128
|
-
|
|
140
|
+
b
|
|
129
141
|
end
|
|
130
142
|
end
|
data/lib/apiculture/version.rb
CHANGED
data/lib/apiculture.rb
CHANGED
|
@@ -35,8 +35,7 @@ module Apiculture
|
|
|
35
35
|
def name_as_string; name.to_s; end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
class RouteParameter <
|
|
39
|
-
def name_as_string; name.to_s; end
|
|
38
|
+
class RouteParameter < Parameter
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
class PossibleResponse < Struct.new(:http_status_code, :description, :jsonable_object_example)
|
|
@@ -119,9 +118,9 @@ module Apiculture
|
|
|
119
118
|
# Route parameters are always required, and all the parameters specified
|
|
120
119
|
# using +route_param+ should also be included in the path given for the route
|
|
121
120
|
# definition
|
|
122
|
-
def route_param(name, description)
|
|
121
|
+
def route_param(name, description, ruby_type = String, cast: IDENTITY_PROC)
|
|
123
122
|
@apiculture_action_definition ||= ActionDefinition.new
|
|
124
|
-
@apiculture_action_definition.route_parameters << RouteParameter.new(name, description)
|
|
123
|
+
@apiculture_action_definition.route_parameters << RouteParameter.new(name, description, required=false, ruby_type, cast)
|
|
125
124
|
end
|
|
126
125
|
|
|
127
126
|
# Add a possible response, specifying the code and the JSON Response by example.
|
|
@@ -245,12 +244,22 @@ module Apiculture
|
|
|
245
244
|
# Pick out all the defined parameters and set up a block that can validate them
|
|
246
245
|
# when the action is called. With that, set up the actual Sinatra method that will
|
|
247
246
|
# respond to the request.
|
|
248
|
-
parametric_checker_proc = parametric_validator_proc_from(action_def.parameters)
|
|
247
|
+
parametric_checker_proc = parametric_validator_proc_from(action_def.parameters + action_def.route_parameters)
|
|
249
248
|
public_send(http_verb, path, options) do |*matched_sinatra_route_params|
|
|
250
|
-
|
|
249
|
+
route_params = []
|
|
250
|
+
action_def.route_parameters.each_with_index do |route_param, index|
|
|
251
|
+
# Apply the type cast and save it (since using our override we can mutate the params)
|
|
252
|
+
value_after_type_cast = AC_APPLY_TYPECAST_PROC.call(route_param.cast_proc_or_method, params[route_param.name])
|
|
253
|
+
route_params[index] = value_after_type_cast
|
|
254
|
+
|
|
255
|
+
# Ensure the typecast value adheres to the enforced Ruby type
|
|
256
|
+
AC_CHECK_TYPE_PROC.call(route_param, route_params[index])
|
|
257
|
+
# ..permit it in the strong parameters if we support them
|
|
258
|
+
AC_PERMIT_PROC.call(route_params, route_param.name)
|
|
259
|
+
end
|
|
251
260
|
instance_exec(¶metric_checker_proc)
|
|
252
261
|
# Execute the original action via instance_exec, passing along the route args
|
|
253
|
-
instance_exec(*
|
|
262
|
+
instance_exec(*route_params, &blk)
|
|
254
263
|
end
|
|
255
264
|
|
|
256
265
|
# Reset for the subsequent action definition
|
|
@@ -27,6 +27,11 @@ describe "Apiculture.api_documentation" do
|
|
|
27
27
|
route_param :id, 'Pancake ID to delete'
|
|
28
28
|
api_method :delete, '/pancake/:id' do
|
|
29
29
|
end
|
|
30
|
+
|
|
31
|
+
desc 'Pancake ingredients are in the URL'
|
|
32
|
+
route_param :topping_id, 'Pancake topping ID', Fixnum, cast: :to_i
|
|
33
|
+
api_method :get, '/pancake/with/:topping_id' do |topping_id|
|
|
34
|
+
end
|
|
30
35
|
end
|
|
31
36
|
}
|
|
32
37
|
|
|
@@ -63,6 +63,24 @@ describe Apiculture::MethodDocumentation do
|
|
|
63
63
|
expect(generated_html).not_to include('<h3>Request parameters</h3>')
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
it 'generates HTML from an ActionDefinition with a casted route param' do
|
|
67
|
+
definition = Apiculture::ActionDefinition.new
|
|
68
|
+
|
|
69
|
+
definition.description = "This adds a topping to a pancake"
|
|
70
|
+
|
|
71
|
+
definition.route_parameters << Apiculture::RouteParameter.new(:topping_id, 'ID of the pancake topping', Fixnum, cast: :to_i)
|
|
72
|
+
definition.http_verb = 'get'
|
|
73
|
+
definition.path = '/pancake/:topping_id'
|
|
74
|
+
|
|
75
|
+
documenter = described_class.new(definition)
|
|
76
|
+
|
|
77
|
+
generated_html = documenter.to_html_fragment
|
|
78
|
+
generated_markdown = documenter.to_markdown
|
|
79
|
+
expect(generated_html).to include('<h3>URL parameters</h3>')
|
|
80
|
+
expect(generated_html).to include('Type after cast')
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
|
|
66
84
|
it 'generates Markdown from an ActionDefinition with a mountpoint' do
|
|
67
85
|
definition = Apiculture::ActionDefinition.new
|
|
68
86
|
|
data/spec/apiculture_spec.rb
CHANGED
|
@@ -191,7 +191,94 @@ describe "Apiculture" do
|
|
|
191
191
|
post '/thing', {number: '123'}
|
|
192
192
|
expect(last_response.body).to eq('Total success')
|
|
193
193
|
end
|
|
194
|
+
|
|
195
|
+
it 'ensures current behaviour for route params is not changed' do
|
|
196
|
+
@app_class = Class.new(Sinatra::Base) do
|
|
197
|
+
settings.show_exceptions = false
|
|
198
|
+
settings.raise_errors = true
|
|
199
|
+
extend Apiculture
|
|
200
|
+
|
|
201
|
+
route_param :number, "Number of the thing"
|
|
202
|
+
api_method :post, '/thing/:number' do
|
|
203
|
+
raise "Casted to int" if params[:number] == 123
|
|
204
|
+
'Total success'
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
post '/thing/123'
|
|
208
|
+
expect(last_response.body).to eq('Total success')
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'ensures current behaviour when no route params are present does not change' do
|
|
212
|
+
@app_class = Class.new(Sinatra::Base) do
|
|
213
|
+
settings.show_exceptions = false
|
|
214
|
+
settings.raise_errors = true
|
|
215
|
+
extend Apiculture
|
|
216
|
+
|
|
217
|
+
param :number, "Number of the thing", Integer, cast: :to_i
|
|
218
|
+
api_method :post, '/thing' do
|
|
219
|
+
raise "Behaviour changed" unless params[:number] == 123
|
|
220
|
+
'Total success'
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
post '/thing', {number: '123'}
|
|
224
|
+
expect(last_response.body).to eq('Total success')
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'applies a symbol typecast by calling a method on the route parameter value' do
|
|
228
|
+
@app_class = Class.new(Sinatra::Base) do
|
|
229
|
+
settings.show_exceptions = false
|
|
230
|
+
settings.raise_errors = true
|
|
231
|
+
extend Apiculture
|
|
232
|
+
|
|
233
|
+
route_param :number, "Number of the thing", Integer, :cast => :to_i
|
|
234
|
+
api_method :post, '/thing/:number' do
|
|
235
|
+
raise "Not cast" unless params[:number] == 123
|
|
236
|
+
'Total success'
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
post '/thing/123'
|
|
240
|
+
expect(last_response.body).to eq('Total success')
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
it 'cast block arguments to the right type', run: true do
|
|
245
|
+
@app_class = Class.new(Sinatra::Base) do
|
|
246
|
+
settings.show_exceptions = false
|
|
247
|
+
settings.raise_errors = true
|
|
248
|
+
extend Apiculture
|
|
249
|
+
|
|
250
|
+
route_param :number, "Number of the thing", Fixnum, :cast => :to_i
|
|
251
|
+
api_method :post, '/thing/:number' do |number|
|
|
252
|
+
raise "Not cast" unless number.class == Fixnum
|
|
253
|
+
'Total success'
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
post '/thing/123'
|
|
257
|
+
expect(last_response.body).to eq('Total success')
|
|
258
|
+
end
|
|
259
|
+
|
|
194
260
|
|
|
261
|
+
it 'merges route_params and regular params' do
|
|
262
|
+
@app_class = Class.new(Sinatra::Base) do
|
|
263
|
+
settings.show_exceptions = false
|
|
264
|
+
settings.raise_errors = true
|
|
265
|
+
extend Apiculture
|
|
266
|
+
|
|
267
|
+
param :number, "Number of the thing", Integer, :cast => :to_i
|
|
268
|
+
route_param :id, "Id of the thingy", Fixnum, :cast => :to_i
|
|
269
|
+
route_param :awesome, "Hash of the thingy"
|
|
270
|
+
|
|
271
|
+
api_method :post, '/thing/:id/:awesome' do |id|
|
|
272
|
+
raise 'Not merged' unless params.has_key?("id")
|
|
273
|
+
raise 'Not merged' unless params.has_key?("awesome")
|
|
274
|
+
'Thanks'
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
post '/thing/1/true', {number: '123'}
|
|
278
|
+
expect(last_response.body).to eq('Thanks')
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
|
|
195
282
|
it 'applies a Proc typecast by calling the proc (for example - for ISO8601 time)' do
|
|
196
283
|
@app_class = Class.new(Sinatra::Base) do
|
|
197
284
|
settings.show_exceptions = false
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: apiculture
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Julik Tarkhanov
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2016-06-01 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: sinatra
|
|
@@ -149,14 +149,14 @@ dependencies:
|
|
|
149
149
|
requirements:
|
|
150
150
|
- - "~>"
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: 2
|
|
152
|
+
version: '2'
|
|
153
153
|
type: :development
|
|
154
154
|
prerelease: false
|
|
155
155
|
version_requirements: !ruby/object:Gem::Requirement
|
|
156
156
|
requirements:
|
|
157
157
|
- - "~>"
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: 2
|
|
159
|
+
version: '2'
|
|
160
160
|
- !ruby/object:Gem::Dependency
|
|
161
161
|
name: simplecov
|
|
162
162
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -179,6 +179,7 @@ extra_rdoc_files:
|
|
|
179
179
|
- LICENSE.txt
|
|
180
180
|
- README.md
|
|
181
181
|
files:
|
|
182
|
+
- ".travis.yml"
|
|
182
183
|
- Gemfile
|
|
183
184
|
- LICENSE.txt
|
|
184
185
|
- README.md
|