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 ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
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 "ZenTest"
10
- gem "rcov"
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
- ZenTest (4.6.2)
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
- ZenTest
114
- capybara (>= 0.4.0)
93
+ RedCloth
115
94
  rails (= 3.0.11)
116
- rcov
95
+ rake
96
+ redcarpet
117
97
  rspec-rails
118
98
  sqlite3
data/README.rdoc CHANGED
@@ -0,0 +1,3 @@
1
+ = Rails API documentation generator
2
+
3
+ {<img src="https://secure.travis-ci.org/Pajk/rails-restapi.png?branch=master" alt="Build Status" />}[http://travis-ci.org/Pajk/rails-restapi]
@@ -4,21 +4,12 @@ module Restapi
4
4
 
5
5
  def index
6
6
  respond_to do |format|
7
- format.json { render :json => Restapi.to_json(params[:resource], params[:method]) }
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
- <tr> \
13
- <td><a href='<%= m.doc_url %>'><%= m.http_method %> <%= m.api_url %></a></td> \
14
- <td width='60%'><%= m['short_description'] %></td> \
15
- </tr> \
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(api) { %> \
34
+ <% _.each(resource.methods, function(m) { %> \
33
35
  <hr><div class=''> \
34
- <div class='pull-right small'><a href='<%= api.doc_url %>'> >>> </a></div> \
36
+ <div class='pull-right small'><a href='<%= m.doc_url %>'> >>> </a></div> \
35
37
  <div> \
36
- <a href='#description-<%= api.name %>' class='accordion-toggle' data-toggle='collapse' data-parent='#accordion'> \
37
- <h3><%= api.http_method %> <%= api.api_url %></a><br> \
38
- <small><%= api.short_description %></small></h3>\
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-<%= api.name %>' class='collapse accordion-body'> \
41
- <%= api.full_description %> \
42
- <% if(api.errors != '') { %> \
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(api.errors, function(err) { %> \
54
+ <% _.each(m.errors, function(err) { %> \
45
55
  <%= err.code %> \
46
56
  <%= err.description %> \
47
57
  <br> \
48
58
  <% }) %> \
49
59
  <% } %> \
50
- <% if(api.params != ''){ %> \
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(api.params, function(val) { %> \
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><a href='<%= docs.doc_url %>'><%= docs.name %></a><span class='divider'>/</span></li> \
72
- <li><a href='<%= resource.doc_url %>'><%= resource.name %></a><span class='divider'>/</span></li> \
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
- <div class='page-header'><h1><%= method.http_method %> <%= method.api_url %><br> \
76
- <small><%= method.short_description %></small></h1> \
77
- </div> \
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 = '/' + window.location.pathname.split('/')[1];
8
- Backbone.history.start({pushState: true, root: base});
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
- this.render('index');
14
+ var url = window.location.pathname + '.json';
15
+ this.render('index', url);
15
16
  },
16
17
 
17
18
  resource: function(resource) {
18
- this.render('resource');
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
- this.render('method');
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(window.location.pathname + '.json', function(data) {
27
- $('#api-title').html(data.docs.name).attr('href', data.docs.doc_url);
28
- $('footer').html(data.docs.copyright);
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").append(html);
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"
@@ -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(resource_name, method_name)
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
- @method_descriptions[key] ||= Restapi::MethodDescription.new(method_name, resource_name, self)
29
+ # add method description key to resource description
30
+ resource = define_resource_description(controller)
34
31
 
35
- # add mapi key to resource api
36
- define_resource_description(resource_name).add_method(key)
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(resource_name, &block)
43
- resource_name = get_resource_name(resource_name)
40
+ def define_resource_description(controller, &block)
41
+ resource_name = get_resource_name(controller)
44
42
 
45
- @resource_descriptions[resource_name] ||= Restapi::ResourceDescription.new(resource_name, &block)
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 = nil
94
- @last_errors = Array.new
95
- @last_params = Hash.new
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
- resource_descriptions.collect { |_,v| v.to_json }
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 && klass.ancestors.include?(ActionController::Base)
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. Use this
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.last_api_args = args
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[param_name.to_sym] = Restapi::ParamDescription.new(param_name, *args, &block)
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
- method_name = method_name.to_sym
84
- resource_name = self.controller_name
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
- mapi.params.each do |_, param|
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