restapi 0.0.2 → 0.0.3
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/.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
|