apipie-rails 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.
- data/Gemfile.lock +5 -3
- data/README.rst +688 -0
- data/apipie-rails.gemspec +2 -4
- data/app/controllers/apipie/apipies_controller.rb +73 -41
- data/app/views/apipie/apipies/index.html.erb +10 -3
- data/app/views/apipie/apipies/method.html.erb +5 -2
- data/app/views/apipie/apipies/resource.html.erb +10 -3
- data/lib/apipie-rails.rb +1 -0
- data/lib/apipie/apipie_module.rb +28 -79
- data/lib/apipie/application.rb +194 -97
- data/lib/apipie/client/generator.rb +5 -4
- data/lib/apipie/configuration.rb +112 -0
- data/lib/apipie/dsl_definition.rb +93 -16
- data/lib/apipie/extractor.rb +12 -5
- data/lib/apipie/extractor/collector.rb +1 -1
- data/lib/apipie/extractor/recorder.rb +2 -1
- data/lib/apipie/extractor/writer.rb +11 -4
- data/lib/apipie/helpers.rb +15 -4
- data/lib/apipie/markup.rb +3 -4
- data/lib/apipie/method_description.rb +28 -22
- data/lib/apipie/resource_description.rb +44 -42
- data/lib/apipie/routing.rb +3 -1
- data/lib/apipie/static_dispatcher.rb +0 -1
- data/lib/apipie/version.rb +1 -1
- data/lib/generators/apipie/install/README +6 -0
- data/lib/generators/apipie/install/install_generator.rb +25 -0
- data/lib/generators/apipie/install/templates/initializer.rb.erb +7 -0
- data/lib/tasks/apipie.rake +31 -39
- data/spec/controllers/api/v1/architectures_controller_spec.rb +30 -0
- data/spec/controllers/api/v2/architectures_controller_spec.rb +12 -0
- data/spec/controllers/apipies_controller_spec.rb +18 -12
- data/spec/controllers/users_controller_spec.rb +56 -19
- data/spec/dummy/app/controllers/api/base_controller.rb +4 -0
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +32 -0
- data/spec/dummy/app/controllers/api/v1/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/api/v2/architectures_controller.rb +32 -0
- data/spec/dummy/app/controllers/api/v2/base_controller.rb +11 -0
- data/spec/dummy/app/controllers/twitter_example_controller.rb +1 -1
- data/spec/dummy/app/controllers/users_controller.rb +2 -3
- data/spec/dummy/config/initializers/apipie.rb +29 -6
- data/spec/lib/method_description_spec.rb +29 -0
- data/spec/lib/param_description_spec.rb +41 -0
- data/spec/lib/resource_description_spec.rb +28 -0
- data/spec/spec_helper.rb +1 -1
- metadata +99 -164
- data/README.rdoc +0 -367
- data/lib/apipie/client/base.rb +0 -133
- data/lib/apipie/client/cli_command.rb +0 -130
- data/lib/apipie/client/main.rb +0 -101
- data/lib/apipie/client/rest_client_oauth.rb +0 -19
- data/lib/apipie/client/template/Gemfile.tt +0 -3
- data/lib/apipie/client/template/README.tt +0 -3
- data/lib/apipie/client/template/Rakefile.tt +0 -2
- data/lib/apipie/client/template/a_name.gemspec.tt +0 -23
- data/lib/apipie/client/template/bin/bin.rb.tt +0 -30
- data/lib/apipie/client/template/lib/a_name.rb.tt +0 -27
- data/lib/apipie/client/template/lib/a_name/commands/cli.rb.tt +0 -22
- data/lib/apipie/client/template/lib/a_name/config.yml +0 -6
- data/lib/apipie/client/template/lib/a_name/resources/resource.rb.tt +0 -22
- data/lib/apipie/client/template/lib/a_name/version.rb.tt +0 -3
- data/lib/apipie/client/thor.rb +0 -21
- data/rubygem-apipie-rails.spec +0 -122
- data/spec/lib/parameter_description_spec.rb +0 -41
data/apipie-rails.gemspec
CHANGED
@@ -16,13 +16,11 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
+
s.add_dependency "rails", ">= 3.0.10"
|
19
20
|
s.add_development_dependency "rspec-rails"
|
20
|
-
s.add_development_dependency "rails", ">= 3.0.10"
|
21
21
|
s.add_development_dependency "sqlite3"
|
22
22
|
s.add_development_dependency "minitest"
|
23
|
-
s.add_development_dependency "
|
23
|
+
s.add_development_dependency "maruku"
|
24
24
|
s.add_development_dependency "RedCloth"
|
25
25
|
s.add_development_dependency "rake"
|
26
|
-
s.add_development_dependency "rest-client"
|
27
|
-
s.add_development_dependency "oauth"
|
28
26
|
end
|
@@ -2,61 +2,39 @@ module Apipie
|
|
2
2
|
class ApipiesController < ActionController::Base
|
3
3
|
layout Apipie.configuration.layout
|
4
4
|
|
5
|
+
around_filter :set_script_name
|
6
|
+
|
5
7
|
def index
|
8
|
+
|
9
|
+
params[:version] ||= Apipie.configuration.default_version
|
10
|
+
|
11
|
+
get_format
|
12
|
+
|
6
13
|
respond_to do |format|
|
7
14
|
|
8
15
|
if Apipie.configuration.use_cache?
|
9
|
-
|
10
|
-
if [:resource, :method, :format].any? { |p| params[p].to_s =~ /\W/ }
|
11
|
-
head :bad_request and return
|
12
|
-
end
|
13
|
-
|
14
|
-
path << "/" << params[:resource] if params[:resource].present?
|
15
|
-
path << "/" << params[:method] if params[:method].present?
|
16
|
-
if params[:format].present?
|
17
|
-
path << ".#{params[:format]}"
|
18
|
-
else
|
19
|
-
path << ".html"
|
20
|
-
end
|
21
|
-
cache_file = File.join(Apipie.configuration.cache_dir, path)
|
22
|
-
if File.exists?(cache_file)
|
23
|
-
content_type = case params[:format]
|
24
|
-
when "json" then "application/json"
|
25
|
-
else "text/html"
|
26
|
-
end
|
27
|
-
send_file cache_file, :type => content_type, :disposition => "inline"
|
28
|
-
else
|
29
|
-
Rails.logger.error("API doc cache not found for '#{path}'. Perhaps you have forgot to run `rake apipie:cache`")
|
30
|
-
head :not_found
|
31
|
-
end
|
32
|
-
return
|
16
|
+
render_from_cache and return
|
33
17
|
end
|
34
18
|
|
35
19
|
Apipie.reload_documentation if Apipie.configuration.reload_controllers?
|
36
|
-
@doc = Apipie.to_json(params[:resource], params[:method])
|
20
|
+
@doc = Apipie.to_json(params[:version], params[:resource], params[:method])
|
37
21
|
|
38
22
|
format.json do
|
39
23
|
render :json => @doc
|
40
24
|
end
|
41
25
|
|
42
26
|
format.html do
|
43
|
-
|
27
|
+
@versions = Apipie.available_versions
|
44
28
|
@doc = @doc[:docs]
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@resource = @doc[:resources].first
|
55
|
-
if @resource == 'null'
|
56
|
-
render 'apipie_404', :status => 404
|
57
|
-
else
|
58
|
-
render 'resource'
|
59
|
-
end
|
29
|
+
@resource = @doc[:resources].first if params[:resource].present?
|
30
|
+
@method = @resource[:methods].first if params[:method].present?
|
31
|
+
|
32
|
+
if @resource && @method
|
33
|
+
render 'method'
|
34
|
+
elsif @resource
|
35
|
+
render 'resource'
|
36
|
+
elsif params[:resource].present? || params[:method].present?
|
37
|
+
render 'apipie_404', :status => 404
|
60
38
|
else
|
61
39
|
render 'index'
|
62
40
|
end
|
@@ -64,5 +42,59 @@ module Apipie
|
|
64
42
|
end
|
65
43
|
end
|
66
44
|
|
45
|
+
private
|
46
|
+
|
47
|
+
def get_format
|
48
|
+
params[:format] = :html unless params[:version].sub!('.html', '').nil?
|
49
|
+
params[:format] = :json unless params[:version].sub!('.json', '').nil?
|
50
|
+
request.format = params[:format] if params[:format]
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_from_cache
|
54
|
+
path = Apipie.configuration.doc_base_url.dup
|
55
|
+
if [:resource, :method, :format].any? { |p| params[p].to_s =~ /\W/ }
|
56
|
+
head :bad_request and return
|
57
|
+
end
|
58
|
+
# version can contain dot, but only one in row
|
59
|
+
if params[:version].to_s.gsub(".", "") =~ /\W/ ||
|
60
|
+
params[:version].to_s =~ /\.\./
|
61
|
+
head :bad_request and return
|
62
|
+
end
|
63
|
+
|
64
|
+
path << "/" << params[:version] if params[:version].present?
|
65
|
+
path << "/" << params[:resource] if params[:resource].present?
|
66
|
+
path << "/" << params[:method] if params[:method].present?
|
67
|
+
if params[:format].present?
|
68
|
+
path << ".#{params[:format]}"
|
69
|
+
else
|
70
|
+
path << ".html"
|
71
|
+
end
|
72
|
+
|
73
|
+
# we sanitize the params before so in ideal case, this condition
|
74
|
+
# will be never satisfied. It's here for cases somebody adds new
|
75
|
+
# param into the path later and forgets about sanitation.
|
76
|
+
if path =~ /\.\./
|
77
|
+
head :bad_request and return
|
78
|
+
end
|
79
|
+
|
80
|
+
cache_file = File.join(Apipie.configuration.cache_dir, path)
|
81
|
+
if File.exists?(cache_file)
|
82
|
+
content_type = case params[:format]
|
83
|
+
when "json" then "application/json"
|
84
|
+
else "text/html"
|
85
|
+
end
|
86
|
+
send_file cache_file, :type => content_type, :disposition => "inline"
|
87
|
+
else
|
88
|
+
Rails.logger.error("API doc cache not found for '#{path}'. Perhaps you have forgot to run `rake apipie:cache`")
|
89
|
+
head :not_found
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_script_name
|
94
|
+
Apipie.request_script_name = request.env["SCRIPT_NAME"]
|
95
|
+
yield
|
96
|
+
ensure
|
97
|
+
Apipie.request_script_name = nil
|
98
|
+
end
|
67
99
|
end
|
68
100
|
end
|
@@ -1,14 +1,21 @@
|
|
1
1
|
<ul class='breadcrumb'>
|
2
|
-
<li class='active'><a href='<%= @doc[:doc_url] %>.html'><%= @doc[:name] %></a></li>
|
2
|
+
<li class='active'><a href='<%= @doc[:doc_url] %>.html'><%= @doc[:name] %> <%= @doc[:resources].values.first[:version] %></a></li>
|
3
|
+
<% if @versions && @versions.size > 1 %>
|
4
|
+
<li class='pull-right'>
|
5
|
+
<%= @versions.collect { |v| link_to v, Apipie.full_url(v) }.join(' / ').html_safe %>
|
6
|
+
</li>
|
7
|
+
<% end %>
|
3
8
|
</ul>
|
4
9
|
|
5
|
-
<div><%= @doc[:info]
|
10
|
+
<div><%= raw @doc[:info] %></div>
|
6
11
|
|
7
12
|
<h1 class='page-header'>Resources</h1>
|
8
13
|
|
9
14
|
<% @doc[:resources].sort_by(&:first).each do |key, api| %>
|
10
15
|
<h2>
|
11
|
-
<a href='<%= api[:doc_url] %>.html'
|
16
|
+
<a href='<%= api[:doc_url] %>.html'>
|
17
|
+
<%= api[:name] %>
|
18
|
+
</a><br>
|
12
19
|
<small><%= api[:short_description] %></small>
|
13
20
|
</h2>
|
14
21
|
<table class='table'>
|
@@ -1,10 +1,13 @@
|
|
1
1
|
<ul class='breadcrumb'>
|
2
2
|
<li>
|
3
|
-
<a href='<%= @doc[:doc_url] %>.html'><%= @doc[:name] %></a>
|
3
|
+
<a href='<%= @doc[:doc_url] %>.html'><%= @doc[:name] %> <%= @resource[:version] %></a>
|
4
4
|
<span class='divider'>/</span>
|
5
5
|
</li>
|
6
6
|
<li>
|
7
|
-
<a href='<%= @resource[:doc_url] %>.html'
|
7
|
+
<a href='<%= @resource[:doc_url] %>.html'>
|
8
|
+
<%= @resource[:name] %>
|
9
|
+
<% if @resource[:version] %><% end %>
|
10
|
+
</a>
|
8
11
|
<span class='divider'>/</span>
|
9
12
|
</li>
|
10
13
|
<li class='active'><%= @method[:name] %></li>
|
@@ -1,11 +1,18 @@
|
|
1
1
|
<ul class='breadcrumb'>
|
2
|
-
<li
|
3
|
-
|
2
|
+
<li>
|
3
|
+
<a href='<%= @doc[:doc_url] %>.html'><%= @doc[:name] %> <%= @resource[:version] %></a>
|
4
|
+
<span class='divider'>/</span>
|
5
|
+
</li>
|
6
|
+
<li class='active'>
|
7
|
+
<%= @resource[:name] %>
|
8
|
+
<% if @resource[:version] %><% end %>
|
9
|
+
</li>
|
4
10
|
</ul>
|
5
11
|
|
6
12
|
<div class='page-header'>
|
7
13
|
<h1>
|
8
|
-
<%= @resource[:name]
|
14
|
+
<%= @resource[:name] %>
|
15
|
+
<br>
|
9
16
|
<small><%= raw @resource[:short_description] %></small>
|
10
17
|
</h1>
|
11
18
|
</div>
|
data/lib/apipie-rails.rb
CHANGED
data/lib/apipie/apipie_module.rb
CHANGED
@@ -8,8 +8,9 @@ module Apipie
|
|
8
8
|
@application ||= Apipie::Application.new
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.to_json(resource_name = nil, method_name = nil)
|
12
|
-
|
11
|
+
def self.to_json(version = nil, resource_name = nil, method_name = nil)
|
12
|
+
version ||= Apipie.configuration.default_version
|
13
|
+
app.to_json(version, resource_name, method_name)
|
13
14
|
end
|
14
15
|
|
15
16
|
# all calls delegated to Apipie::Application instance
|
@@ -25,89 +26,37 @@ module Apipie
|
|
25
26
|
@configuration ||= Configuration.new
|
26
27
|
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
alias_method :validate?, :validate
|
33
|
-
alias_method :required_by_default?, :required_by_default
|
34
|
-
|
35
|
-
# matcher to be used in Dir.glob to find controllers to be reloaded e.g.
|
36
|
-
#
|
37
|
-
# "#{Rails.root}/app/controllers/api/*.rb"
|
38
|
-
attr_accessor :api_controllers_matcher
|
39
|
-
|
40
|
-
# set to true if you want to reload the controllers at each refresh of the
|
41
|
-
# documentation. It requires +:api_controllers_matcher+ to be set to work
|
42
|
-
# properly.
|
43
|
-
attr_writer :reload_controllers
|
44
|
-
|
45
|
-
def reload_controllers?
|
46
|
-
@reload_controllers = Rails.env.development? unless defined? @reload_controllers
|
47
|
-
return @reload_controllers && @api_controllers_matcher
|
48
|
-
end
|
49
|
-
|
50
|
-
# set to true if you want to use pregenerated documentation cache and avoid
|
51
|
-
# generating the documentation on runtime (usefull for production
|
52
|
-
# environment).
|
53
|
-
# You can generate the cache by running
|
54
|
-
#
|
55
|
-
# rake apipie:cache
|
56
|
-
attr_accessor :use_cache
|
57
|
-
alias_method :use_cache?, :use_cache
|
58
|
-
|
59
|
-
attr_writer :cache_dir
|
60
|
-
def cache_dir
|
61
|
-
@cache_dir ||= File.join(Rails.root, "public", "apipie-cache")
|
62
|
-
end
|
63
|
-
|
64
|
-
# if there is not obvious reason why the DSL should be turned on (no
|
65
|
-
# validations, cache turned on etc.), it's disabled to avoid unneeded
|
66
|
-
# allocation. It you need the DSL for other reasons, you can force the
|
67
|
-
# activation.
|
68
|
-
attr_writer :force_dsl
|
69
|
-
def force_dsl?
|
70
|
-
@force_dsl
|
71
|
-
end
|
72
|
-
|
73
|
-
# array of controller names (strings) (might include actions as well)
|
74
|
-
# to be ignored # when extracting description form calls.
|
75
|
-
# e.g. %w[Api::CommentsController Api::PostsController#post]
|
76
|
-
attr_writer :ignored_by_recorder
|
77
|
-
def ignored_by_recorder
|
78
|
-
@ignored_by_recorder ||= []
|
79
|
-
@ignored_by_recorder.map(&:to_s)
|
80
|
-
end
|
29
|
+
def self.debug(message)
|
30
|
+
puts message if Apipie.configuration.debug
|
31
|
+
end
|
81
32
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
33
|
+
# get application description for given or default version
|
34
|
+
def self.app_info(version = nil)
|
35
|
+
if app_info_version_valid? version
|
36
|
+
Apipie.markup_to_html(self.configuration.app_info[version])
|
37
|
+
elsif app_info_version_valid? Apipie.configuration.default_version
|
38
|
+
Apipie.markup_to_html(self.configuration.app_info[Apipie.configuration.default_version])
|
39
|
+
else
|
40
|
+
"Another API description"
|
89
41
|
end
|
42
|
+
end
|
90
43
|
|
91
|
-
|
92
|
-
|
44
|
+
def self.api_base_url(version = nil)
|
45
|
+
if api_base_url_version_valid? version
|
46
|
+
self.configuration.api_base_url[version]
|
47
|
+
elsif api_base_url_version_valid? Apipie.configuration.default_version
|
48
|
+
self.configuration.api_base_url[Apipie.configuration.default_version]
|
49
|
+
else
|
50
|
+
"/api"
|
93
51
|
end
|
52
|
+
end
|
94
53
|
|
95
|
-
|
96
|
-
|
97
|
-
|
54
|
+
def self.app_info_version_valid?(version)
|
55
|
+
version && self.configuration.app_info.has_key?(version)
|
56
|
+
end
|
98
57
|
|
99
|
-
|
100
|
-
|
101
|
-
@app_name = "Another API"
|
102
|
-
@app_info = "Another API description"
|
103
|
-
@copyright = nil
|
104
|
-
@validate = true
|
105
|
-
@required_by_default = false
|
106
|
-
@api_base_url = ""
|
107
|
-
@doc_base_url = "/apipie"
|
108
|
-
@layout = "apipie/apipie"
|
109
|
-
@disqus_shortname = nil
|
110
|
-
end
|
58
|
+
def self.api_base_url_version_valid?(version)
|
59
|
+
version && self.configuration.api_base_url.has_key?(version)
|
111
60
|
end
|
112
61
|
|
113
62
|
end
|
data/lib/apipie/application.rb
CHANGED
@@ -12,147 +12,210 @@ module Apipie
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
attr_accessor :
|
16
|
-
|
15
|
+
attr_accessor :last_dsl_data
|
16
|
+
|
17
|
+
attr_reader :resource_descriptions
|
17
18
|
|
18
19
|
def initialize
|
19
20
|
super
|
20
|
-
|
21
|
-
@resource_descriptions = Hash.new
|
21
|
+
init_env
|
22
22
|
clear_last
|
23
23
|
end
|
24
24
|
|
25
|
+
def available_versions
|
26
|
+
@resource_descriptions.keys.sort
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_resource_id(controller, resource_id)
|
30
|
+
@controller_to_resource_id[controller] = resource_id
|
31
|
+
end
|
32
|
+
|
25
33
|
# create new method api description
|
26
|
-
def define_method_description(controller, method_name)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
def define_method_description(controller, method_name, versions = [])
|
35
|
+
return if ignored?(controller, method_name)
|
36
|
+
ret_method_description = nil
|
37
|
+
|
38
|
+
versions = controller_versions(controller) if versions.empty?
|
39
|
+
|
40
|
+
versions.each do |version|
|
41
|
+
resource_name_with_version = "#{version}##{get_resource_name(controller)}"
|
42
|
+
resource_description = get_resource_description(resource_name_with_version)
|
32
43
|
|
33
|
-
|
44
|
+
if resource_description.nil?
|
45
|
+
resource_description = define_resource_description(controller, version)
|
46
|
+
end
|
47
|
+
|
48
|
+
method_description = Apipie::MethodDescription.new(method_name, resource_description, self)
|
34
49
|
|
35
|
-
|
50
|
+
# we create separate method description for each version in
|
51
|
+
# case the method belongs to more versions. We return just one
|
52
|
+
# becuase the version doesn't matter for the purpose it's used
|
53
|
+
# (to wrap the original version with validators)
|
54
|
+
ret_method_description ||= method_description
|
55
|
+
resource_description.add_method_description(method_description)
|
56
|
+
end
|
36
57
|
|
37
|
-
|
58
|
+
return ret_method_description
|
38
59
|
end
|
39
60
|
|
40
61
|
# create new resource api description
|
41
|
-
def define_resource_description(controller,
|
62
|
+
def define_resource_description(controller, version, dsl_data = nil)
|
63
|
+
return if ignored?(controller)
|
64
|
+
|
42
65
|
resource_name = get_resource_name(controller)
|
66
|
+
resource_description = @resource_descriptions[version][resource_name]
|
67
|
+
if resource_description
|
68
|
+
# we already defined the description somewhere (probably in
|
69
|
+
# some method. Updating just meta data from dsl
|
70
|
+
resource_description.update_from_dsl_data(dsl_data) if dsl_data
|
71
|
+
else
|
72
|
+
resource_description = Apipie::ResourceDescription.new(controller, resource_name, dsl_data, version)
|
73
|
+
|
74
|
+
Apipie.debug("@resource_descriptions[#{version}][#{resource_name}] = #{resource_description}")
|
75
|
+
@resource_descriptions[version][resource_name] ||= resource_description
|
76
|
+
end
|
77
|
+
|
78
|
+
return resource_description
|
79
|
+
end
|
43
80
|
|
44
|
-
|
81
|
+
# recursively searches what versions has the controller specified in
|
82
|
+
# resource_description? It's used to derivate the default value of
|
83
|
+
# versions for methods.
|
84
|
+
def controller_versions(controller)
|
85
|
+
ret = @controller_versions[controller]
|
86
|
+
return ret unless ret.empty?
|
87
|
+
if controller == ActionController::Base || controller.nil?
|
88
|
+
return [Apipie.configuration.default_version]
|
89
|
+
else
|
90
|
+
return controller_versions(controller.superclass)
|
91
|
+
end
|
92
|
+
end
|
45
93
|
|
46
|
-
|
47
|
-
|
94
|
+
def set_controller_versions(controller, versions)
|
95
|
+
@controller_versions[controller] = versions
|
48
96
|
end
|
49
97
|
|
50
98
|
def add_method_description_args(method, path, desc)
|
51
|
-
@
|
99
|
+
@last_dsl_data[:api_args] << MethodDescription::Api.new(method, path, desc)
|
52
100
|
end
|
53
101
|
|
54
102
|
def add_example(example)
|
55
|
-
@
|
103
|
+
@last_dsl_data[:examples] << example.strip_heredoc
|
56
104
|
end
|
57
105
|
|
58
106
|
# check if there is some saved description
|
59
107
|
def apipie_provided?
|
60
|
-
true unless
|
108
|
+
true unless last_dsl_data[:api_args].blank?
|
61
109
|
end
|
62
110
|
|
63
111
|
# get api for given method
|
64
112
|
#
|
65
113
|
# There are two ways how this method can be used:
|
66
114
|
# 1) Specify both parameters
|
67
|
-
# resource_name:
|
115
|
+
# resource_name:
|
116
|
+
# controller class - UsersController
|
117
|
+
# string with resource name (plural) and version - "v1#users"
|
68
118
|
# method_name: name of the method (string or symbol)
|
119
|
+
#
|
69
120
|
# 2) Specify only first parameter:
|
70
121
|
# resource_name: string containing both resource and method name joined
|
71
|
-
# with #
|
122
|
+
# with '#' symbol.
|
123
|
+
# - "users#create" get default version
|
124
|
+
# - "v2#users#create" get specific version
|
72
125
|
def get_method_description(resource_name, method_name = nil)
|
73
|
-
resource_name
|
74
|
-
|
75
|
-
|
126
|
+
if resource_name.is_a?(String)
|
127
|
+
crumbs = resource_name.split('#')
|
128
|
+
if method_name.nil?
|
129
|
+
method_name = crumbs.pop
|
130
|
+
end
|
131
|
+
resource_name = crumbs.join("#")
|
132
|
+
resource_description = get_resource_description(resource_name)
|
133
|
+
elsif resource_name.respond_to? :apipie_resource_descriptions
|
134
|
+
resource_description = get_resource_description(resource_name)
|
135
|
+
else
|
136
|
+
raise ArgumentError.new("Resource #{resource_name} does not exists.")
|
137
|
+
end
|
138
|
+
unless resource_description.nil?
|
139
|
+
resource_description.method_description(method_name.to_sym)
|
140
|
+
end
|
76
141
|
end
|
77
142
|
alias :[] :get_method_description
|
78
143
|
|
79
|
-
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
# Clear all apis in this application.
|
99
|
-
def clear
|
100
|
-
@resource_descriptions.clear
|
101
|
-
@method_descriptions.clear
|
102
|
-
end
|
103
|
-
|
104
|
-
# clear all saved data
|
105
|
-
def clear_last
|
106
|
-
@last_api_args = []
|
107
|
-
@last_errors = []
|
108
|
-
@last_params = []
|
109
|
-
@last_description = nil
|
110
|
-
@last_examples = []
|
111
|
-
@last_see = nil
|
112
|
-
@last_formats = []
|
113
|
-
end
|
144
|
+
# options:
|
145
|
+
# => "users"
|
146
|
+
# => "v2#users"
|
147
|
+
# => V2::UsersController
|
148
|
+
def get_resource_description(resource, version = nil)
|
149
|
+
if resource.is_a?(String)
|
150
|
+
crumbs = resource.split('#')
|
151
|
+
if crumbs.size == 2
|
152
|
+
version = crumbs.first
|
153
|
+
end
|
154
|
+
version ||= Apipie.configuration.default_version
|
155
|
+
if @resource_descriptions.has_key?(version)
|
156
|
+
return @resource_descriptions[version][crumbs.last]
|
157
|
+
end
|
158
|
+
else
|
159
|
+
resource_name = get_resource_name(resource)
|
160
|
+
if version
|
161
|
+
resource_name = "#{version}##{resource_name}"
|
162
|
+
end
|
114
163
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
164
|
+
if resource_name.nil?
|
165
|
+
return nil
|
166
|
+
end
|
167
|
+
resource_description = get_resource_description(resource_name)
|
168
|
+
if resource_description && resource_description.controller == resource
|
169
|
+
return resource_description
|
170
|
+
end
|
171
|
+
end
|
120
172
|
end
|
121
173
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
174
|
+
# get all versions of resource description
|
175
|
+
def get_resource_descriptions(resource)
|
176
|
+
available_versions.map do |version|
|
177
|
+
get_resource_description(resource, version)
|
178
|
+
end.compact
|
126
179
|
end
|
127
180
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
181
|
+
# get all versions of method description
|
182
|
+
def get_method_descriptions(resource, method)
|
183
|
+
get_resource_descriptions(resource).map do |resource_description|
|
184
|
+
resource_description.method_description(method.to_sym)
|
185
|
+
end.compact
|
132
186
|
end
|
133
187
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
188
|
+
def remove_method_description(resource, versions, method_name)
|
189
|
+
versions.each do |version|
|
190
|
+
resource = get_resource_name(resource)
|
191
|
+
if resource_description = get_resource_description("#{version}##{resource}")
|
192
|
+
resource_description.remove_method_description(method_name)
|
193
|
+
end
|
194
|
+
end
|
138
195
|
end
|
139
196
|
|
140
|
-
|
141
|
-
|
142
|
-
@
|
143
|
-
|
144
|
-
end
|
197
|
+
# initialize variables for gathering dsl data
|
198
|
+
def init_env
|
199
|
+
@resource_descriptions = HashWithIndifferentAccess.new { |h, version| h[version] = {} }
|
200
|
+
@controller_to_resource_id = {}
|
145
201
|
|
146
|
-
|
147
|
-
|
148
|
-
@last_params.clear
|
149
|
-
params
|
202
|
+
# what versions does the controller belong in (specified by resource_description)?
|
203
|
+
@controller_versions = Hash.new { |h, controller| h[controller] = [] }
|
150
204
|
end
|
151
|
-
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
205
|
+
# clear all saved data
|
206
|
+
def clear_last
|
207
|
+
@last_dsl_data = {
|
208
|
+
:api_args => [],
|
209
|
+
:errors => [],
|
210
|
+
:params => [],
|
211
|
+
:resouce_id => nil,
|
212
|
+
:short_description => nil,
|
213
|
+
:description => nil,
|
214
|
+
:examples => [],
|
215
|
+
:see => nil,
|
216
|
+
:formats => nil,
|
217
|
+
:api_versions => []
|
218
|
+
}
|
156
219
|
end
|
157
220
|
|
158
221
|
def recorded_examples
|
@@ -170,26 +233,28 @@ module Apipie
|
|
170
233
|
@recorded_examples = nil
|
171
234
|
end
|
172
235
|
|
173
|
-
def to_json(resource_name, method_name)
|
236
|
+
def to_json(version, resource_name, method_name)
|
174
237
|
|
175
238
|
_resources = if resource_name.blank?
|
176
239
|
# take just resources which have some methods because
|
177
240
|
# we dont want to show eg ApplicationController as resource
|
178
|
-
resource_descriptions.inject({}) do |result, (k,v)|
|
241
|
+
resource_descriptions[version].inject({}) do |result, (k,v)|
|
179
242
|
result[k] = v.to_json unless v._methods.blank?
|
180
243
|
result
|
181
244
|
end
|
182
245
|
else
|
183
|
-
[@resource_descriptions[resource_name].to_json(method_name)]
|
246
|
+
[@resource_descriptions[version][resource_name].to_json(method_name)]
|
184
247
|
end
|
185
248
|
|
249
|
+
url_args = Apipie.configuration.version_in_url ? version : ''
|
250
|
+
|
186
251
|
{
|
187
252
|
:docs => {
|
188
253
|
:name => Apipie.configuration.app_name,
|
189
|
-
:info => Apipie.
|
254
|
+
:info => Apipie.app_info(version),
|
190
255
|
:copyright => Apipie.configuration.copyright,
|
191
|
-
:doc_url => Apipie.full_url(
|
192
|
-
:api_url => Apipie.
|
256
|
+
:doc_url => Apipie.full_url(url_args),
|
257
|
+
:api_url => Apipie.api_base_url(version),
|
193
258
|
:resources => _resources
|
194
259
|
}
|
195
260
|
}
|
@@ -200,7 +265,10 @@ module Apipie
|
|
200
265
|
end
|
201
266
|
|
202
267
|
def reload_documentation
|
268
|
+
rails_mark_classes_for_reload
|
269
|
+
init_env
|
203
270
|
reload_examples
|
271
|
+
|
204
272
|
api_controllers_paths.each do |f|
|
205
273
|
load_controller_from_file f
|
206
274
|
end
|
@@ -218,8 +286,21 @@ module Apipie
|
|
218
286
|
def get_resource_name(klass)
|
219
287
|
if klass.class == String
|
220
288
|
klass
|
289
|
+
elsif @controller_to_resource_id.has_key?(klass)
|
290
|
+
@controller_to_resource_id[klass]
|
221
291
|
elsif klass.respond_to?(:controller_name)
|
292
|
+
return nil if klass == ActionController::Base
|
222
293
|
klass.controller_name
|
294
|
+
else
|
295
|
+
raise "Apipie: Can not resolve resource #{klass} name."
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def get_resource_version(resource_description)
|
300
|
+
if resource_description.respond_to? :_version
|
301
|
+
resource_description._version
|
302
|
+
else
|
303
|
+
Apipie.configuration.default_version
|
223
304
|
end
|
224
305
|
end
|
225
306
|
|
@@ -228,5 +309,21 @@ module Apipie
|
|
228
309
|
controller_class_name.constantize
|
229
310
|
end
|
230
311
|
|
312
|
+
def ignored?(controller, method = nil)
|
313
|
+
ignored = Apipie.configuration.ignored
|
314
|
+
return true if ignored.include?(controller.name)
|
315
|
+
return true if ignored.include?("#{controller.name}##{method}")
|
316
|
+
end
|
317
|
+
|
318
|
+
# Since Rails 3.2, the classes are reloaded only on file change.
|
319
|
+
# We need to reload all the controller classes to rebuild the
|
320
|
+
# docs, therefore we just force to reload all the code. This
|
321
|
+
# happens only when reload_controllers is set to true and only
|
322
|
+
# when showing the documentation.
|
323
|
+
def rails_mark_classes_for_reload
|
324
|
+
ActiveSupport::DescendantsTracker.clear
|
325
|
+
ActiveSupport::Dependencies.clear
|
326
|
+
end
|
327
|
+
|
231
328
|
end
|
232
329
|
end
|