restapi 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -0
- data/Gemfile +4 -7
- data/Gemfile.lock +5 -25
- data/README.rdoc +3 -0
- data/app/controllers/restapi/restapis_controller.rb +3 -12
- data/app/public/restapi/javascripts/jst.js +41 -22
- data/app/public/restapi/javascripts/restapi.js +4 -5
- data/app/public/restapi/javascripts/routers/documentation_router.js +13 -8
- data/lib/restapi.rb +1 -2
- data/lib/restapi/application.rb +28 -23
- data/lib/restapi/dsl_definition.rb +8 -12
- data/lib/restapi/helpers.rb +2 -2
- data/lib/restapi/markup.rb +45 -0
- data/lib/restapi/method_description.rb +82 -16
- data/lib/restapi/param_description.rb +36 -11
- data/lib/restapi/resource_description.rb +18 -10
- data/lib/restapi/restapi_module.rb +6 -7
- data/lib/restapi/static_dispatcher.rb +2 -0
- data/lib/restapi/validator.rb +40 -31
- data/lib/restapi/version.rb +1 -1
- data/restapi.gemspec +1 -1
- data/spec/controllers/users_controller_spec.rb +156 -32
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/dogs_controller.rb +0 -2
- data/spec/dummy/app/controllers/users_controller.rb +20 -5
- data/spec/dummy/config/database.yml +2 -3
- data/spec/dummy/config/environment.rb +3 -0
- data/spec/dummy/config/initializers/restapi.rb +6 -2
- data/spec/dummy/config/routes.rb +11 -64
- metadata +7 -21
- data/spec/dummy/app/views/users/doc.html.erb +0 -24
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,15 +1,12 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
3
|
gem "rails", "3.0.11"
|
4
|
-
gem "capybara", ">= 0.4.0"
|
5
4
|
gem "sqlite3"
|
6
5
|
|
7
6
|
group :development, :test do
|
8
7
|
gem "rspec-rails"
|
9
|
-
gem "
|
10
|
-
gem "
|
8
|
+
#gem "rcov"
|
9
|
+
gem "redcarpet"
|
10
|
+
gem "RedCloth"
|
11
|
+
gem "rake"
|
11
12
|
end
|
12
|
-
|
13
|
-
# To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
|
14
|
-
#gem 'ruby-debug'
|
15
|
-
# gem 'ruby-debug19'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
|
4
|
+
RedCloth (4.2.9)
|
5
5
|
abstract (1.0.0)
|
6
6
|
actionmailer (3.0.11)
|
7
7
|
actionpack (= 3.0.11)
|
@@ -31,19 +31,9 @@ GEM
|
|
31
31
|
activesupport (3.0.11)
|
32
32
|
arel (2.0.10)
|
33
33
|
builder (2.1.2)
|
34
|
-
capybara (1.1.2)
|
35
|
-
mime-types (>= 1.16)
|
36
|
-
nokogiri (>= 1.3.3)
|
37
|
-
rack (>= 1.0.0)
|
38
|
-
rack-test (>= 0.5.4)
|
39
|
-
selenium-webdriver (~> 2.0)
|
40
|
-
xpath (~> 0.1.4)
|
41
|
-
childprocess (0.3.1)
|
42
|
-
ffi (~> 1.0.6)
|
43
34
|
diff-lcs (1.1.3)
|
44
35
|
erubis (2.6.6)
|
45
36
|
abstract (>= 1.0.0)
|
46
|
-
ffi (1.0.11)
|
47
37
|
i18n (0.5.0)
|
48
38
|
json (1.6.5)
|
49
39
|
mail (2.2.19)
|
@@ -52,8 +42,6 @@ GEM
|
|
52
42
|
mime-types (~> 1.16)
|
53
43
|
treetop (~> 1.4.8)
|
54
44
|
mime-types (1.17.2)
|
55
|
-
multi_json (1.0.4)
|
56
|
-
nokogiri (1.5.0)
|
57
45
|
polyglot (0.3.3)
|
58
46
|
rack (1.2.5)
|
59
47
|
rack-mount (0.6.14)
|
@@ -75,9 +63,9 @@ GEM
|
|
75
63
|
rdoc (~> 3.4)
|
76
64
|
thor (~> 0.14.4)
|
77
65
|
rake (0.9.2.2)
|
78
|
-
rcov (1.0.0)
|
79
66
|
rdoc (3.12)
|
80
67
|
json (~> 1.4)
|
68
|
+
redcarpet (2.1.1)
|
81
69
|
rspec (2.8.0)
|
82
70
|
rspec-core (~> 2.8.0)
|
83
71
|
rspec-expectations (~> 2.8.0)
|
@@ -91,28 +79,20 @@ GEM
|
|
91
79
|
activesupport (>= 3.0)
|
92
80
|
railties (>= 3.0)
|
93
81
|
rspec (~> 2.8.0)
|
94
|
-
rubyzip (0.9.6.1)
|
95
|
-
selenium-webdriver (2.19.0)
|
96
|
-
childprocess (>= 0.2.5)
|
97
|
-
ffi (~> 1.0.9)
|
98
|
-
multi_json (~> 1.0.4)
|
99
|
-
rubyzip
|
100
82
|
sqlite3 (1.3.5)
|
101
83
|
thor (0.14.6)
|
102
84
|
treetop (1.4.10)
|
103
85
|
polyglot
|
104
86
|
polyglot (>= 0.3.1)
|
105
87
|
tzinfo (0.3.31)
|
106
|
-
xpath (0.1.4)
|
107
|
-
nokogiri (~> 1.3)
|
108
88
|
|
109
89
|
PLATFORMS
|
110
90
|
ruby
|
111
91
|
|
112
92
|
DEPENDENCIES
|
113
|
-
|
114
|
-
capybara (>= 0.4.0)
|
93
|
+
RedCloth
|
115
94
|
rails (= 3.0.11)
|
116
|
-
|
95
|
+
rake
|
96
|
+
redcarpet
|
117
97
|
rspec-rails
|
118
98
|
sqlite3
|
data/README.rdoc
CHANGED
@@ -4,21 +4,12 @@ module Restapi
|
|
4
4
|
|
5
5
|
def index
|
6
6
|
respond_to do |format|
|
7
|
-
format.json
|
7
|
+
format.json do
|
8
|
+
render :json => Restapi.to_json(params[:resource], params[:method])
|
9
|
+
end
|
8
10
|
format.html
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
12
|
-
protected
|
13
|
-
|
14
|
-
helper_method :restapi_javascript_src
|
15
|
-
def restapi_javascript_src(file)
|
16
|
-
"#{Restapi.configuration.doc_base_url}/javascripts/#{file}"
|
17
|
-
end
|
18
|
-
|
19
|
-
helper_method :restapi_stylesheet_src
|
20
|
-
def restapi_stylesheet_src(file)
|
21
|
-
"#{Restapi.configuration.doc_base_url}/stylesheets/#{file}"
|
22
|
-
end
|
23
14
|
end
|
24
15
|
end
|
@@ -9,11 +9,13 @@ Restapi.Templates.Index = _.template(
|
|
9
9
|
<thead><tr><th>Resource</th><th>Description</th></tr></thead> \
|
10
10
|
<tbody> \
|
11
11
|
<% _.each(api.methods, function(m) { %> \
|
12
|
-
|
13
|
-
<
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
<% _.each(m.apis, function(api) { %> \
|
13
|
+
<tr> \
|
14
|
+
<td><a href='<%= m.doc_url %>'><%= api.http_method %> <%= api.api_url %></a></td> \
|
15
|
+
<td width='60%'><%= api.short_description %></td> \
|
16
|
+
</tr> \
|
17
|
+
<% }) %>\
|
18
|
+
<% }) %> \
|
17
19
|
</tbody> \
|
18
20
|
</table> \
|
19
21
|
<% }) %>");
|
@@ -29,30 +31,38 @@ Restapi.Templates.Resource = _.template(
|
|
29
31
|
<div><%= resource.full_description %></div> \
|
30
32
|
<% } %> \
|
31
33
|
<div class='accordion' id='accordion'> \
|
32
|
-
<% _.each(resource.methods, function(
|
34
|
+
<% _.each(resource.methods, function(m) { %> \
|
33
35
|
<hr><div class=''> \
|
34
|
-
<div class='pull-right small'><a href='<%=
|
36
|
+
<div class='pull-right small'><a href='<%= m.doc_url %>'> >>> </a></div> \
|
35
37
|
<div> \
|
36
|
-
|
37
|
-
<h3
|
38
|
-
|
38
|
+
<% _.each(m.apis, function(api) { %> \
|
39
|
+
<h3> \
|
40
|
+
<a href='#description-<%= m.name %>' \
|
41
|
+
class='accordion-toggle' \
|
42
|
+
data-toggle='collapse' \
|
43
|
+
data-parent='#accordion'> \
|
44
|
+
<%= api.http_method %> <%= api.api_url %> \
|
45
|
+
</a> <br> \
|
46
|
+
<small><%= api.short_description %></small> \
|
47
|
+
</h3> \
|
48
|
+
<% }) %> \
|
39
49
|
</div> \
|
40
|
-
<div id='description-<%=
|
41
|
-
<%=
|
42
|
-
<% if(
|
50
|
+
<div id='description-<%= m.name %>' class='collapse accordion-body'> \
|
51
|
+
<%= m.full_description %> \
|
52
|
+
<% if(m.errors != '') { %> \
|
43
53
|
<h2>Errors</h2> \
|
44
|
-
<% _.each(
|
54
|
+
<% _.each(m.errors, function(err) { %> \
|
45
55
|
<%= err.code %> \
|
46
56
|
<%= err.description %> \
|
47
57
|
<br> \
|
48
58
|
<% }) %> \
|
49
59
|
<% } %> \
|
50
|
-
<% if(
|
60
|
+
<% if(m.params != ''){ %> \
|
51
61
|
<h2>Params</h2> \
|
52
62
|
<table class='table'> \
|
53
63
|
<thead><tr><th>Param name</th><th>Description</th></tr></thead> \
|
54
64
|
<tbody> \
|
55
|
-
<% _.each(
|
65
|
+
<% _.each(m.params, function(val) { %> \
|
56
66
|
<tr><td><strong><%= val.name %></strong><br>\
|
57
67
|
<small><%= val.required ? 'required' : 'optional' %></small></td> \
|
58
68
|
<td><%= val.description %><br>\
|
@@ -68,13 +78,22 @@ Restapi.Templates.Resource = _.template(
|
|
68
78
|
|
69
79
|
Restapi.Templates.Method = _.template(
|
70
80
|
"<ul class='breadcrumb'> \
|
71
|
-
<li
|
72
|
-
|
81
|
+
<li> \
|
82
|
+
<a href='<%= docs.doc_url %>'><%= docs.name %></a> \
|
83
|
+
<span class='divider'>/</span> \
|
84
|
+
</li> \
|
85
|
+
<li> \
|
86
|
+
<a href='<%= resource.doc_url %>'><%= resource.name %></a> \
|
87
|
+
<span class='divider'>/</span> \
|
88
|
+
</li> \
|
73
89
|
<li class='active'><%= method.name %></li> \
|
74
90
|
</ul> \
|
75
|
-
|
76
|
-
<
|
77
|
-
|
91
|
+
<% _.each(method.apis, function(api) { %> \
|
92
|
+
<div class='page-header'> \
|
93
|
+
<h1><%= api.http_method %> <%= api.api_url %><br> \
|
94
|
+
<small><%= api.short_description %></small></h1> \
|
95
|
+
</div> \
|
96
|
+
<% }) %> \
|
78
97
|
<div> \
|
79
98
|
<%= method.full_description %> \
|
80
99
|
<% if(method.errors != '') { %> \
|
@@ -105,4 +124,4 @@ Restapi.Templates.Method = _.template(
|
|
105
124
|
</tbody> \
|
106
125
|
</table> \
|
107
126
|
<% } %> \
|
108
|
-
</div>");
|
127
|
+
</div>");
|
@@ -1,14 +1,13 @@
|
|
1
1
|
var Restapi = {
|
2
2
|
Routers: {},
|
3
3
|
Templates: {},
|
4
|
+
Rendered: false,
|
4
5
|
|
5
6
|
init: function() {
|
6
7
|
new Restapi.Routers.Documentation();
|
7
|
-
var base =
|
8
|
-
Backbone.history.start({
|
9
|
-
}
|
10
|
-
|
11
|
-
baseurl: function() { return document.location.toString().replace(/#.*/,""); }
|
8
|
+
var base = window.location.pathname;
|
9
|
+
Backbone.history.start({root: base});
|
10
|
+
}
|
12
11
|
};
|
13
12
|
|
14
13
|
$(document).ready(function() {
|
@@ -11,21 +11,25 @@ Restapi.Routers.Documentation = Backbone.Router.extend({
|
|
11
11
|
},
|
12
12
|
|
13
13
|
index: function() {
|
14
|
-
|
14
|
+
var url = window.location.pathname + '.json';
|
15
|
+
this.render('index', url);
|
15
16
|
},
|
16
17
|
|
17
18
|
resource: function(resource) {
|
18
|
-
|
19
|
+
var url = [window.location.pathname, resource + '.json'].join('/');
|
20
|
+
this.render('resource', url);
|
19
21
|
},
|
20
22
|
|
21
23
|
method: function(resource, method) {
|
22
|
-
|
24
|
+
var url = [window.location.pathname, resource, method +'.json'].join('/');
|
25
|
+
this.render('method', url);
|
23
26
|
},
|
24
27
|
|
25
|
-
render: function(type) {
|
26
|
-
this.data = $.getJSON(
|
27
|
-
|
28
|
-
|
28
|
+
render: function(type, url) {
|
29
|
+
this.data = $.getJSON(url, function(data) {
|
30
|
+
if(!Restapi.rendered) {
|
31
|
+
$('footer').html(data.docs.copyright);
|
32
|
+
}
|
29
33
|
|
30
34
|
var html = '';
|
31
35
|
if (type == 'index') {
|
@@ -40,7 +44,8 @@ Restapi.Routers.Documentation = Backbone.Router.extend({
|
|
40
44
|
});
|
41
45
|
}
|
42
46
|
|
43
|
-
$("#container").
|
47
|
+
$("#container").html(html);
|
48
|
+
Restapi.rendered = true;
|
44
49
|
});
|
45
50
|
}
|
46
51
|
|
data/lib/restapi.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'active_support/dependencies'
|
2
|
-
require 'rdoc'
|
3
|
-
require 'rdoc/markup/to_html'
|
4
2
|
|
5
3
|
# add path to restapi controller to ActiveSupport paths
|
6
4
|
%w{ controllers views }.each do |dir|
|
@@ -11,6 +9,7 @@ require 'rdoc/markup/to_html'
|
|
11
9
|
end
|
12
10
|
|
13
11
|
require "restapi/routing"
|
12
|
+
require "restapi/markup"
|
14
13
|
require "restapi/restapi_module"
|
15
14
|
require "restapi/method_description"
|
16
15
|
require "restapi/resource_description"
|
data/lib/restapi/application.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'ostruct'
|
2
1
|
require 'restapi/static_dispatcher'
|
3
2
|
|
4
3
|
module Restapi
|
@@ -23,37 +22,38 @@ module Restapi
|
|
23
22
|
end
|
24
23
|
|
25
24
|
# create new method api description
|
26
|
-
def define_method_description(
|
27
|
-
resource_name = get_resource_name(resource_name)
|
28
|
-
|
29
|
-
puts "defining api for #{resource_name}:#{method_name}"
|
30
|
-
|
25
|
+
def define_method_description(controller, method_name)
|
31
26
|
# create new or get existing api
|
27
|
+
resource_name = get_resource_name(controller)
|
32
28
|
key = [resource_name, method_name].join('#')
|
33
|
-
|
29
|
+
# add method description key to resource description
|
30
|
+
resource = define_resource_description(controller)
|
34
31
|
|
35
|
-
|
36
|
-
|
32
|
+
method_description = Restapi::MethodDescription.new(method_name, resource, self)
|
33
|
+
|
34
|
+
@method_descriptions[key] ||= method_description
|
37
35
|
|
38
36
|
@method_descriptions[key]
|
39
37
|
end
|
40
38
|
|
41
39
|
# create new resource api description
|
42
|
-
def define_resource_description(
|
43
|
-
resource_name = get_resource_name(
|
40
|
+
def define_resource_description(controller, &block)
|
41
|
+
resource_name = get_resource_name(controller)
|
44
42
|
|
45
|
-
|
43
|
+
# puts "defining api for #{resource_name}"
|
44
|
+
|
45
|
+
@resource_descriptions[resource_name] ||=
|
46
|
+
Restapi::ResourceDescription.new(controller, resource_name, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_method_description_args(args)
|
50
|
+
@last_api_args << MethodDescription::Api.new(args)
|
46
51
|
end
|
47
52
|
|
48
53
|
# check if there is some saved description
|
49
54
|
def restapi_provided?
|
50
55
|
true unless last_api_args.blank?
|
51
56
|
end
|
52
|
-
|
53
|
-
# List of all the apis defined in the given scope (and its sub-scopes).
|
54
|
-
# def mapis_for_resource(resource_name)
|
55
|
-
# @method_descriptions.select { |key,val| key.first == controller_name }
|
56
|
-
# end
|
57
57
|
|
58
58
|
# get api for given method
|
59
59
|
def get_method_description(resource_name, method_name)
|
@@ -90,9 +90,9 @@ module Restapi
|
|
90
90
|
|
91
91
|
# clear all saved data
|
92
92
|
def clear_last
|
93
|
-
@last_api_args =
|
94
|
-
@last_errors =
|
95
|
-
@last_params =
|
93
|
+
@last_api_args = []
|
94
|
+
@last_errors = []
|
95
|
+
@last_params = []
|
96
96
|
@last_description = nil
|
97
97
|
end
|
98
98
|
|
@@ -124,7 +124,12 @@ module Restapi
|
|
124
124
|
def to_json(resource_name, method_name)
|
125
125
|
|
126
126
|
_resources = if resource_name.blank?
|
127
|
-
|
127
|
+
# take just resources which have some methods because
|
128
|
+
# we dont want to show eg ApplicationController as resource
|
129
|
+
resource_descriptions.inject({}) do |result, (k,v)|
|
130
|
+
result[k] = v.to_json unless v._methods.blank?
|
131
|
+
result
|
132
|
+
end
|
128
133
|
else
|
129
134
|
[@resource_descriptions[resource_name].to_json(method_name)]
|
130
135
|
end
|
@@ -134,7 +139,7 @@ module Restapi
|
|
134
139
|
'name' => Restapi.configuration.app_name,
|
135
140
|
'info' => Restapi.configuration.app_info,
|
136
141
|
'copyright' => Restapi.configuration.copyright,
|
137
|
-
'doc_url' => Restapi.configuration.doc_base_url,
|
142
|
+
'doc_url' => "#{ENV["RAILS_RELATIVE_URL_ROOT"]}#{Restapi.configuration.doc_base_url}",
|
138
143
|
'api_url' => Restapi.configuration.api_base_url,
|
139
144
|
'resources' => _resources
|
140
145
|
}
|
@@ -146,7 +151,7 @@ module Restapi
|
|
146
151
|
def get_resource_name(klass)
|
147
152
|
if klass.class == String
|
148
153
|
klass
|
149
|
-
elsif klass.class == Class &&
|
154
|
+
elsif klass.class == Class && ActionController::Base.descendants.include?(klass)
|
150
155
|
klass.controller_name
|
151
156
|
end
|
152
157
|
end
|
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
module Restapi
|
4
4
|
|
5
|
-
# DSL is a module that provides #api, #error, #param, #error.
|
6
|
-
# when you'd like to use restapi outside the top level scope.
|
5
|
+
# DSL is a module that provides #api, #error, #param, #error.
|
7
6
|
|
8
7
|
module DSL
|
9
8
|
|
@@ -29,7 +28,7 @@ module Restapi
|
|
29
28
|
# :method => "GET"
|
30
29
|
#
|
31
30
|
def api(args)
|
32
|
-
Restapi.
|
31
|
+
Restapi.add_method_description_args(args)
|
33
32
|
end
|
34
33
|
|
35
34
|
# Describe the next method.
|
@@ -70,7 +69,7 @@ module Restapi
|
|
70
69
|
# end
|
71
70
|
#
|
72
71
|
def param(param_name, *args, &block)
|
73
|
-
Restapi.last_params
|
72
|
+
Restapi.last_params << Restapi::ParamDescription.new(param_name, *args, &block)
|
74
73
|
end
|
75
74
|
|
76
75
|
# create method api and redefine newly added method
|
@@ -80,12 +79,9 @@ module Restapi
|
|
80
79
|
|
81
80
|
return unless Restapi.restapi_provided?
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
# remove mapi if exists and create new one
|
87
|
-
Restapi.remove_method_description(resource_name, method_name)
|
88
|
-
mapi = Restapi.define_method_description(resource_name, method_name)
|
82
|
+
# remove method description if exists and create new one
|
83
|
+
Restapi.remove_method_description(self, method_name)
|
84
|
+
description = Restapi.define_method_description(self, method_name)
|
89
85
|
|
90
86
|
# redefine method only if validation is turned on
|
91
87
|
if Restapi.configuration.validate == true
|
@@ -94,7 +90,7 @@ module Restapi
|
|
94
90
|
|
95
91
|
define_method(method_name) do |*args|
|
96
92
|
|
97
|
-
|
93
|
+
description.params.each do |_, param|
|
98
94
|
|
99
95
|
# check if required parameters are present
|
100
96
|
if param.required && !params.has_key?(param.name)
|
@@ -116,4 +112,4 @@ module Restapi
|
|
116
112
|
|
117
113
|
end # def method_added
|
118
114
|
end # module DSL
|
119
|
-
end # module Restapi
|
115
|
+
end # module Restapi
|