api_taster 0.3.0 → 0.4.0
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.
- data/README.md +14 -6
- data/app/assets/javascripts/api_taster/app.js +2 -0
- data/app/controllers/api_taster/routes_controller.rb +6 -1
- data/app/views/api_taster/routes/_information_warning_li.html.erb +8 -0
- data/app/views/api_taster/routes/_route_definitions.html.erb +7 -0
- data/app/views/api_taster/routes/index.html.erb +13 -9
- data/app/views/api_taster/routes/missing_definitions.html.erb +12 -0
- data/app/views/api_taster/routes/obsolete_definitions.html.erb +3 -9
- data/config/routes.rb +4 -1
- data/lib/api_taster.rb +4 -0
- data/lib/api_taster/form_builder.rb +18 -10
- data/lib/api_taster/route.rb +15 -1
- data/lib/api_taster/version.rb +1 -1
- data/spec/controllers/api_taster/routes_controller_spec.rb +6 -0
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/form_builder_spec.rb +17 -1
- data/spec/mapper_spec.rb +1 -1
- data/spec/route_spec.rb +14 -0
- metadata +7 -4
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# ApiTaster [](http://travis-ci.org/fredwu/api_taster) [](https://gemnasium.com/fredwu/api_taster)
|
2
2
|
|
3
|
-
A quick and easy way to visually test out your application's API.
|
3
|
+
A quick and easy way to visually test out your Rails application's API.
|
4
4
|
|
5
|
-

|
6
6
|
|
7
7
|
## Why?
|
8
8
|
|
@@ -67,15 +67,23 @@ if Rails.env.development?
|
|
67
67
|
end
|
68
68
|
```
|
69
69
|
|
70
|
-
|
70
|
+
### Share Params with Test Factories
|
71
71
|
|
72
|
-
|
72
|
+
If you use a test factory such as [FactoryGirl](https://github.com/thoughtbot/factory_girl), you can require your test factories and share the params. For example in FactoryGirl you can use the `attributes_for(:name_of_factory)` method.
|
73
|
+
|
74
|
+
### Missing Route Definitions Detection
|
75
|
+
|
76
|
+
Instead of manually finding out which route definitions you need, API Taster provides a warning page that shows you all the missing definitions.
|
77
|
+
|
78
|
+

|
79
|
+
|
80
|
+
### Obsolete / Mismatched Route Definitions Detection
|
73
81
|
|
74
82
|
APIs evolve - especially during the development stage. To keep `ApiTaster.routes` in sync with your route definitions, API Taster provides a warning page that shows you the definitions that are obsolete/mismatched therefore you could correct or remove them.
|
75
83
|
|
76
|
-

|
77
85
|
|
78
|
-
|
86
|
+
### Use with an Engine
|
79
87
|
|
80
88
|
Rails Engines are largely self contained and separated from your main app. Therefore, to use API Taster with an Engine, you would need some extra efforts:
|
81
89
|
|
@@ -2,7 +2,8 @@ module ApiTaster
|
|
2
2
|
class RoutesController < ApplicationController
|
3
3
|
def index
|
4
4
|
@routes = Route.grouped_routes
|
5
|
-
@
|
5
|
+
@has_missing_definitions = Route.missing_definitions.present?
|
6
|
+
@has_obsolete_definitions = Route.obsolete_definitions.present?
|
6
7
|
end
|
7
8
|
|
8
9
|
def show
|
@@ -10,6 +11,10 @@ module ApiTaster
|
|
10
11
|
@inputs = Route.inputs_for(@route)
|
11
12
|
end
|
12
13
|
|
14
|
+
def missing_definitions
|
15
|
+
@missing_definitions = Route.missing_definitions
|
16
|
+
end
|
17
|
+
|
13
18
|
def obsolete_definitions
|
14
19
|
@obsolete_definitions = Route.obsolete_definitions
|
15
20
|
end
|
@@ -2,16 +2,20 @@
|
|
2
2
|
<div id="list-api-div" class="span5">
|
3
3
|
<div class="div-container">
|
4
4
|
<ul class="well nav nav-list">
|
5
|
-
<% if @has_obsolete_definitions %>
|
5
|
+
<% if @has_missing_definitions || @has_obsolete_definitions %>
|
6
6
|
<li class="nav-header">Information</li>
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
<% if @has_missing_definitions %>
|
8
|
+
<%= render 'information_warning_li',
|
9
|
+
:text => 'Missing Definitions Detected',
|
10
|
+
:path => missing_definitions_routes_path
|
11
|
+
%>
|
12
|
+
<% end %>
|
13
|
+
<% if @has_obsolete_definitions %>
|
14
|
+
<%= render 'information_warning_li',
|
15
|
+
:text => 'Obsolete Definitions Detected',
|
16
|
+
:path => obsolete_definitions_routes_path
|
17
|
+
%>
|
18
|
+
<% end %>
|
15
19
|
<% end %>
|
16
20
|
<% @routes.each do |controller, routes| %>
|
17
21
|
<li class="nav-header"><%= controller %></li>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= render 'breadcrumb',
|
2
|
+
:parent => 'Information',
|
3
|
+
:current => 'Missing Definitions Detected',
|
4
|
+
:label => 'Warning',
|
5
|
+
:label_type => 'warning'
|
6
|
+
%>
|
7
|
+
|
8
|
+
<div class="alert alert-warning">
|
9
|
+
<p>The following route definitions are missing from <code>ApiTaster.routes</code>.</p>
|
10
|
+
|
11
|
+
<%= render 'route_definitions', :routes => @missing_definitions %>
|
12
|
+
</div>
|
@@ -5,14 +5,8 @@
|
|
5
5
|
:label_type => 'warning'
|
6
6
|
%>
|
7
7
|
|
8
|
-
<div class="alert alert-
|
9
|
-
<p
|
8
|
+
<div class="alert alert-warning">
|
9
|
+
<p>The following route definitions are found within <code>ApiTaster.routes</code> but they are not defined in your routes. Please feel free to correct or remove them.</p>
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
<% @obsolete_definitions.each do |route| %>
|
14
|
-
<%= route[:verb].downcase %> '<%= route[:path] %>'<%= ", #{route[:params]}" if route[:params].present? %>
|
15
|
-
|
16
|
-
<% end %>
|
17
|
-
end</pre>
|
11
|
+
<%= render 'route_definitions', :routes => @obsolete_definitions %>
|
18
12
|
</div>
|
data/config/routes.rb
CHANGED
data/lib/api_taster.rb
CHANGED
@@ -8,7 +8,11 @@ module ApiTaster
|
|
8
8
|
def self.routes(&block)
|
9
9
|
Route.route_set = Rails.application.routes
|
10
10
|
Route.inputs = {}
|
11
|
+
Route.missing_definitions = []
|
11
12
|
Route.obsolete_definitions = []
|
13
|
+
|
12
14
|
Mapper.instance_eval(&block)
|
15
|
+
|
16
|
+
Route.calculate_missing_definitions
|
13
17
|
end
|
14
18
|
end
|
@@ -20,16 +20,7 @@ module ApiTaster
|
|
20
20
|
|
21
21
|
def add_to_buffer(params, parent_labels = [])
|
22
22
|
params.each do |label, value|
|
23
|
-
if value.is_a?(
|
24
|
-
@_buffer += render(
|
25
|
-
:partial => 'api_taster/routes/param_form_element',
|
26
|
-
:locals => {
|
27
|
-
:label => "#{print_labels(parent_labels)}#{label}",
|
28
|
-
:label_text => label,
|
29
|
-
:value => value
|
30
|
-
}
|
31
|
-
)
|
32
|
-
else
|
23
|
+
if value.is_a?(Hash)
|
33
24
|
parent_labels << label
|
34
25
|
|
35
26
|
@_buffer += render(
|
@@ -38,10 +29,27 @@ module ApiTaster
|
|
38
29
|
)
|
39
30
|
|
40
31
|
add_to_buffer(value, parent_labels)
|
32
|
+
elsif value.is_a?(Array)
|
33
|
+
value.each do |v|
|
34
|
+
add_element_to_buffer(parent_labels, "[#{label}][]", v)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
add_element_to_buffer(parent_labels, label, value)
|
41
38
|
end
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
42
|
+
def add_element_to_buffer(parent_labels, label, value)
|
43
|
+
@_buffer += render(
|
44
|
+
:partial => 'api_taster/routes/param_form_element',
|
45
|
+
:locals => {
|
46
|
+
:label => "#{print_labels(parent_labels)}#{label}",
|
47
|
+
:label_text => label,
|
48
|
+
:value => value.to_s
|
49
|
+
}
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
45
53
|
def print_labels(parent_labels)
|
46
54
|
"[#{parent_labels * ']['}]"
|
47
55
|
end
|
data/lib/api_taster/route.rb
CHANGED
@@ -2,6 +2,7 @@ module ApiTaster
|
|
2
2
|
class Route
|
3
3
|
cattr_accessor :route_set
|
4
4
|
cattr_accessor :inputs
|
5
|
+
cattr_accessor :missing_definitions
|
5
6
|
cattr_accessor :obsolete_definitions
|
6
7
|
|
7
8
|
class << self
|
@@ -13,7 +14,7 @@ module ApiTaster
|
|
13
14
|
next if route.app.is_a?(Sprockets::Environment)
|
14
15
|
next if route.app == ApiTaster::Engine
|
15
16
|
|
16
|
-
if rack_app = discover_rack_app(route.app)
|
17
|
+
if (rack_app = discover_rack_app(route.app)) && rack_app.respond_to?(:routes)
|
17
18
|
rack_app.routes.routes.each do |rack_route|
|
18
19
|
_routes << normalise_route(rack_route, i+=1)
|
19
20
|
end
|
@@ -50,8 +51,21 @@ module ApiTaster
|
|
50
51
|
inputs[route[:id]].collect { |input| split_input(input, route) }
|
51
52
|
end
|
52
53
|
|
54
|
+
def calculate_missing_definitions
|
55
|
+
routes.each do |route|
|
56
|
+
if undefined_route?(route)
|
57
|
+
self.missing_definitions << route
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
53
62
|
private
|
54
63
|
|
64
|
+
def undefined_route?(route)
|
65
|
+
r = inputs_for(route)
|
66
|
+
r.is_a?(Hash) && r.has_key?(:undefined)
|
67
|
+
end
|
68
|
+
|
55
69
|
def discover_rack_app(app)
|
56
70
|
class_name = app.class.name.to_s
|
57
71
|
if class_name == "ActionDispatch::Routing::Mapper::Constraints"
|
data/lib/api_taster/version.rb
CHANGED
@@ -18,6 +18,12 @@ module ApiTaster
|
|
18
18
|
assigns(:inputs).should be_kind_of(Array)
|
19
19
|
end
|
20
20
|
|
21
|
+
it "#missing_definitions" do
|
22
|
+
get :missing_definitions, :use_route => :api_taster
|
23
|
+
|
24
|
+
assigns(:missing_definitions).should be_kind_of(Array)
|
25
|
+
end
|
26
|
+
|
21
27
|
it "#obsolete_definitions" do
|
22
28
|
get :obsolete_definitions, :use_route => :api_taster
|
23
29
|
|
data/spec/dummy/config/routes.rb
CHANGED
data/spec/form_builder_spec.rb
CHANGED
@@ -13,7 +13,9 @@ module ApiTaster
|
|
13
13
|
FormBuilder.new({
|
14
14
|
:hello => 'world',
|
15
15
|
:nested => {
|
16
|
-
:foo => 'bar'
|
16
|
+
:foo => 'bar',
|
17
|
+
:integer => 1,
|
18
|
+
:array => [1, 2, 3]
|
17
19
|
}
|
18
20
|
})
|
19
21
|
end
|
@@ -25,5 +27,19 @@ module ApiTaster
|
|
25
27
|
it "outputs html" do
|
26
28
|
builder.html.should match('bar')
|
27
29
|
end
|
30
|
+
|
31
|
+
context "data types" do
|
32
|
+
it "does strings" do
|
33
|
+
builder.html.should match('value="world"')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "does numbers" do
|
37
|
+
builder.html.should match('value="1"')
|
38
|
+
end
|
39
|
+
|
40
|
+
it "does arrays" do
|
41
|
+
builder.html.should match(/name="\[nested\]\[array\]\[\]" value="2"/)
|
42
|
+
end
|
43
|
+
end
|
28
44
|
end
|
29
45
|
end
|
data/spec/mapper_spec.rb
CHANGED
data/spec/route_spec.rb
CHANGED
@@ -23,6 +23,7 @@ module ApiTaster
|
|
23
23
|
resources :comments
|
24
24
|
end
|
25
25
|
mount Rails.application => '/app'
|
26
|
+
mount proc {} => '/rack_app'
|
26
27
|
end
|
27
28
|
|
28
29
|
Route.route_set = routes
|
@@ -71,6 +72,19 @@ module ApiTaster
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
75
|
+
it "#missing_definitions" do
|
76
|
+
routes = ActionDispatch::Routing::RouteSet.new
|
77
|
+
routes.draw do
|
78
|
+
get 'awesome_route' => 'awesome#route'
|
79
|
+
end
|
80
|
+
Rails.application.stub(:routes).and_return(routes)
|
81
|
+
ApiTaster.routes do
|
82
|
+
# nothing
|
83
|
+
end
|
84
|
+
|
85
|
+
Route.missing_definitions.first[:path].should == '/awesome_route'
|
86
|
+
end
|
87
|
+
|
74
88
|
context "private methods" do
|
75
89
|
it "#discover_rack_app" do
|
76
90
|
klass = Class.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: api_taster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.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-06-
|
12
|
+
date: 2012-06-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -182,10 +182,13 @@ files:
|
|
182
182
|
- app/controllers/api_taster/routes_controller.rb
|
183
183
|
- app/helpers/api_taster/application_helper.rb
|
184
184
|
- app/views/api_taster/routes/_breadcrumb.html.erb
|
185
|
+
- app/views/api_taster/routes/_information_warning_li.html.erb
|
185
186
|
- app/views/api_taster/routes/_param_form_element.html.erb
|
186
187
|
- app/views/api_taster/routes/_param_form_legend.html.erb
|
188
|
+
- app/views/api_taster/routes/_route_definitions.html.erb
|
187
189
|
- app/views/api_taster/routes/_undefined_route.html.erb
|
188
190
|
- app/views/api_taster/routes/index.html.erb
|
191
|
+
- app/views/api_taster/routes/missing_definitions.html.erb
|
189
192
|
- app/views/api_taster/routes/obsolete_definitions.html.erb
|
190
193
|
- app/views/api_taster/routes/show.html.erb
|
191
194
|
- app/views/layouts/api_taster/application.html.erb
|
@@ -351,7 +354,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
351
354
|
version: '0'
|
352
355
|
segments:
|
353
356
|
- 0
|
354
|
-
hash:
|
357
|
+
hash: -907459549939205334
|
355
358
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
356
359
|
none: false
|
357
360
|
requirements:
|
@@ -360,7 +363,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
360
363
|
version: '0'
|
361
364
|
segments:
|
362
365
|
- 0
|
363
|
-
hash:
|
366
|
+
hash: -907459549939205334
|
364
367
|
requirements: []
|
365
368
|
rubyforge_project:
|
366
369
|
rubygems_version: 1.8.24
|