apipie-rails 0.0.24 → 0.1.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/.gitignore +1 -1
- data/.travis.yml +6 -0
- data/CHANGELOG.md +97 -0
- data/Gemfile +1 -1
- data/Gemfile.rails30 +5 -0
- data/Gemfile.rails32 +5 -0
- data/Gemfile.rails40 +5 -0
- data/Gemfile.rails41 +5 -0
- data/README.rst +126 -11
- data/apipie-rails.gemspec +1 -1
- data/app/controllers/apipie/apipies_controller.rb +3 -0
- data/app/helpers/apipie_helper.rb +9 -0
- data/app/views/apipie/apipies/_metadata.erb +1 -0
- data/app/views/apipie/apipies/_method_detail.erb +46 -0
- data/app/views/apipie/apipies/_params.html.erb +12 -0
- data/app/views/apipie/apipies/_params_plain.html.erb +4 -0
- data/app/views/apipie/apipies/apipie_checksum.json.erb +1 -0
- data/app/views/apipie/apipies/method.html.erb +1 -37
- data/app/views/apipie/apipies/plain.html.erb +1 -0
- data/app/views/apipie/apipies/resource.html.erb +6 -37
- data/app/views/apipie/apipies/static.html.erb +1 -0
- data/lib/apipie/application.rb +16 -2
- data/lib/apipie/configuration.rb +8 -2
- data/lib/apipie/dsl_definition.rb +25 -6
- data/lib/apipie/error_description.rb +22 -10
- data/lib/apipie/extractor.rb +2 -1
- data/lib/apipie/extractor/writer.rb +8 -6
- data/lib/apipie/method_description.rb +7 -4
- data/lib/apipie/middleware/checksum_in_headers.rb +35 -0
- data/lib/apipie/param_description.rb +25 -4
- data/lib/apipie/resource_description.rb +8 -4
- data/lib/apipie/routing.rb +1 -0
- data/lib/apipie/validator.rb +71 -3
- data/lib/apipie/version.rb +1 -1
- data/lib/tasks/apipie.rake +26 -5
- data/spec/controllers/apipies_controller_spec.rb +2 -0
- data/spec/controllers/concerns_controller_spec.rb +1 -1
- data/spec/controllers/users_controller_spec.rb +130 -19
- data/spec/dummy/app/controllers/api/v1/architectures_controller.rb +1 -0
- data/spec/dummy/app/controllers/api/v2/nested/architectures_controller.rb +22 -20
- data/spec/dummy/app/controllers/concerns/sample_controller.rb +32 -30
- data/spec/dummy/app/controllers/users_controller.rb +18 -5
- data/spec/lib/method_description_spec.rb +22 -0
- data/spec/lib/param_description_spec.rb +77 -0
- data/spec/lib/rake_spec.rb +68 -0
- data/spec/lib/resource_description_spec.rb +18 -0
- data/spec/lib/validator_spec.rb +9 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/rake.rb +21 -0
- metadata +20 -7
- data/CHANGELOG +0 -72
@@ -0,0 +1 @@
|
|
1
|
+
<pre class="prettyprint lang-yaml"><%= meta.to_yaml.gsub(/---\n/, "") %></pre>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<%= raw method[:full_description] %>
|
2
|
+
|
3
|
+
<% unless method[:formats].blank? %>
|
4
|
+
<%= heading('Supported Formats', h_level) %>
|
5
|
+
<%= method[:formats].join(', ') %>
|
6
|
+
<% end %>
|
7
|
+
|
8
|
+
<% unless method[:errors].blank? %>
|
9
|
+
<%= heading('Errors', h_level) %>
|
10
|
+
<% method[:errors].each do |err| %>
|
11
|
+
<%= err[:code] %>
|
12
|
+
<%= err[:description] %>
|
13
|
+
<br>
|
14
|
+
<% unless err[:metadata].blank? %>
|
15
|
+
Metadata:
|
16
|
+
<pre class="prettyprint lang-yaml"><%= err[:metadata].to_yaml %></pre>
|
17
|
+
<% end %>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<% unless method[:metadata].blank? %>
|
22
|
+
<%= heading('Metadata', h_level) %>
|
23
|
+
<%= render(:partial => "metadata", :locals => {:meta => method[:metadata]}) %>
|
24
|
+
<% end %>
|
25
|
+
|
26
|
+
<% unless method[:examples].blank? %>
|
27
|
+
<%= heading('Examples', h_level) %>
|
28
|
+
<% method[:examples].each do |example| %>
|
29
|
+
<pre class="prettyprint"><%= example %></pre>
|
30
|
+
<% end %>
|
31
|
+
<% end %>
|
32
|
+
|
33
|
+
<% unless method[:params].blank? %>
|
34
|
+
<%= heading('Params', h_level) %>
|
35
|
+
<table class='table'>
|
36
|
+
<thead>
|
37
|
+
<tr>
|
38
|
+
<th>Param name</th>
|
39
|
+
<th>Description</th>
|
40
|
+
</tr>
|
41
|
+
</thead>
|
42
|
+
<tbody>
|
43
|
+
<%= render(:partial => "params", :locals => {:params => method[:params]}) %>
|
44
|
+
</tbody>
|
45
|
+
</table>
|
46
|
+
<% end %>
|
@@ -1,6 +1,10 @@
|
|
1
1
|
<% level ||= 0 %>
|
2
2
|
<% col = 255 - level * 5 %>
|
3
3
|
<% params.each do |param| %>
|
4
|
+
<% if !param[:show] %>
|
5
|
+
<%= render(:partial => "params", :locals => {:level => level, :params => param[:params]}) unless param[:params].blank? %>
|
6
|
+
<% next %>
|
7
|
+
<% end %>
|
4
8
|
<tr style='background-color:rgb(<%= "#{col},#{col},#{col}" %>);'>
|
5
9
|
<td>
|
6
10
|
<strong><%= param[:full_name] %> </strong><br>
|
@@ -15,7 +19,15 @@
|
|
15
19
|
<br>
|
16
20
|
Value: <%= param[:validator] %>
|
17
21
|
<% end %>
|
22
|
+
|
23
|
+
<% unless param[:metadata].blank? %>
|
24
|
+
<br>
|
25
|
+
Metadata:
|
26
|
+
<%= render(:partial => "metadata", :locals => {:meta => param[:metadata]}) %>
|
27
|
+
<% end %>
|
28
|
+
|
18
29
|
</td>
|
30
|
+
|
19
31
|
</tr>
|
20
32
|
|
21
33
|
<%= render(:partial => "params", :locals => {:level => level + 1, :params => param[:params]}) unless param[:params].blank? %>
|
@@ -0,0 +1 @@
|
|
1
|
+
{ "checksum": "<%= raw Apipie.checksum %>" }
|
@@ -27,43 +27,7 @@
|
|
27
27
|
Also see <%= @method[:see].map { |s| link_to(s[:description], "#{s[:link]}.html") }.to_sentence.html_safe %>.
|
28
28
|
<% end %>
|
29
29
|
|
30
|
-
<%=
|
31
|
-
|
32
|
-
<% unless @method[:examples].blank? %>
|
33
|
-
<h2>Examples</h2>
|
34
|
-
<% @method[:examples].each do |example| %>
|
35
|
-
<pre class="prettyprint"><%= example %></pre>
|
36
|
-
<% end %>
|
37
|
-
<% end %>
|
38
|
-
|
39
|
-
<% unless @method[:formats].blank? %>
|
40
|
-
<h2>Supported Formats</h2>
|
41
|
-
<%= @method[:formats].join(', ') %>
|
42
|
-
<% end %>
|
43
|
-
|
44
|
-
<% unless @method[:errors].blank? %>
|
45
|
-
<h2>Errors</h2>
|
46
|
-
<% @method[:errors].each do |err| %>
|
47
|
-
<%= err[:code] %>
|
48
|
-
<%= err[:description] %>
|
49
|
-
<br>
|
50
|
-
<% end %>
|
51
|
-
<% end %>
|
52
|
-
|
53
|
-
<% unless @method[:params].blank? %>
|
54
|
-
<h2>Params</h2>
|
55
|
-
<table class='table'>
|
56
|
-
<thead>
|
57
|
-
<tr>
|
58
|
-
<th>Param name</th>
|
59
|
-
<th>Description</th>
|
60
|
-
</tr>
|
61
|
-
</thead>
|
62
|
-
<tbody>
|
63
|
-
<%= render(:partial => "params", :locals => {:params => @method[:params]}) %>
|
64
|
-
</tbody>
|
65
|
-
</table>
|
66
|
-
<% end %>
|
30
|
+
<%= render(:partial => "method_detail", :locals => {:method => @method, :h_level => 2}) %>
|
67
31
|
</div>
|
68
32
|
|
69
33
|
<% content_for :apipie_footer do %>
|
@@ -21,6 +21,11 @@
|
|
21
21
|
<div><%= raw @resource[:full_description] %></div>
|
22
22
|
<% end %>
|
23
23
|
|
24
|
+
<% unless @resource[:metadata].blank? %>
|
25
|
+
<h2>Metadata</h2>
|
26
|
+
<%= render(:partial => "metadata", :locals => {:meta => @resource[:metadata]}) %>
|
27
|
+
<% end %>
|
28
|
+
|
24
29
|
<% unless @resource[:formats].blank? %>
|
25
30
|
<h2>Supported Formats</h2>
|
26
31
|
<%= @resource[:formats].join(', ') %>
|
@@ -52,43 +57,7 @@
|
|
52
57
|
<% end %>
|
53
58
|
|
54
59
|
<div id='description-<%= m[:name] %>' class='collapse accordion-body'>
|
55
|
-
<%=
|
56
|
-
|
57
|
-
<% unless m[:formats].blank? %>
|
58
|
-
<h3>Supported Formats</h3>
|
59
|
-
<%= m[:formats].join(', ') %>
|
60
|
-
<% end %>
|
61
|
-
|
62
|
-
<% unless m[:errors].blank? %>
|
63
|
-
<h3>Errors</h3>
|
64
|
-
<% m[:errors].each do |err| %>
|
65
|
-
<%= err[:code] %>
|
66
|
-
<%= err[:description] %>
|
67
|
-
<br>
|
68
|
-
<% end %>
|
69
|
-
<% end %>
|
70
|
-
|
71
|
-
<% unless m[:examples].blank? %>
|
72
|
-
<h3>Examples</h3>
|
73
|
-
<% m[:examples].each do |example| %>
|
74
|
-
<pre class="prettyprint"><%= example %></pre>
|
75
|
-
<% end %>
|
76
|
-
<% end %>
|
77
|
-
|
78
|
-
<% unless m[:params].blank? %>
|
79
|
-
<h3>Params</h3>
|
80
|
-
<table class='table'>
|
81
|
-
<thead>
|
82
|
-
<tr>
|
83
|
-
<th>Param name</th>
|
84
|
-
<th>Description</th>
|
85
|
-
</tr>
|
86
|
-
</thead>
|
87
|
-
<tbody>
|
88
|
-
<%= render(:partial => "params", :locals => {:params => m[:params]}) %>
|
89
|
-
</tbody>
|
90
|
-
</table>
|
91
|
-
<% end %>
|
60
|
+
<%= render(:partial => "method_detail", :locals => {:method => m, :h_level => 3}) %>
|
92
61
|
</div>
|
93
62
|
<% end %>
|
94
63
|
</div>
|
data/lib/apipie/application.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'apipie/static_dispatcher'
|
2
2
|
require 'yaml'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'json'
|
3
5
|
|
4
6
|
module Apipie
|
5
7
|
|
@@ -208,8 +210,8 @@ module Apipie
|
|
208
210
|
tape_file = File.join(Rails.root,"doc","apipie_examples.yml")
|
209
211
|
if File.exists?(tape_file)
|
210
212
|
#if SafeYAML gem is enabled, it will load examples as an array of Hash, instead of hash
|
211
|
-
if defined?
|
212
|
-
@recorded_examples =
|
213
|
+
if YAML.respond_to?(:safe_load_file) && defined?(SafeYAML)
|
214
|
+
@recorded_examples = SafeYAML.load_file(tape_file, :safe=>false)
|
213
215
|
else
|
214
216
|
@recorded_examples = YAML.load_file(tape_file)
|
215
217
|
end
|
@@ -264,6 +266,18 @@ module Apipie
|
|
264
266
|
api_controllers_paths.each do |f|
|
265
267
|
load_controller_from_file f
|
266
268
|
end
|
269
|
+
@checksum = compute_checksum if Apipie.configuration.update_checksum
|
270
|
+
end
|
271
|
+
|
272
|
+
def compute_checksum
|
273
|
+
all_docs = Apipie.available_versions.inject({}) do |all, version|
|
274
|
+
all.update(version => Apipie.to_json(version))
|
275
|
+
end
|
276
|
+
Digest::MD5.hexdigest(JSON.dump(all_docs))
|
277
|
+
end
|
278
|
+
|
279
|
+
def checksum
|
280
|
+
@checksum ||= compute_checksum
|
267
281
|
end
|
268
282
|
|
269
283
|
# Is there a reason to interpret the DSL for this run?
|
data/lib/apipie/configuration.rb
CHANGED
@@ -4,8 +4,8 @@ module Apipie
|
|
4
4
|
attr_accessor :app_name, :app_info, :copyright, :markup, :disqus_shortname,
|
5
5
|
:api_base_url, :doc_base_url, :required_by_default, :layout,
|
6
6
|
:default_version, :debug, :version_in_url, :namespaced_resources,
|
7
|
-
:validate, :validate_value, :validate_presence, :authenticate, :doc_path
|
8
|
-
|
7
|
+
:validate, :validate_value, :validate_presence, :authenticate, :doc_path,
|
8
|
+
:show_all_examples, :process_params, :update_checksum, :checksum_path
|
9
9
|
|
10
10
|
alias_method :validate?, :validate
|
11
11
|
alias_method :required_by_default?, :required_by_default
|
@@ -36,6 +36,9 @@ module Apipie
|
|
36
36
|
end
|
37
37
|
alias_method :validate_presence?, :validate_presence
|
38
38
|
|
39
|
+
def process_value?
|
40
|
+
@process_params
|
41
|
+
end
|
39
42
|
# set to true if you want to use pregenerated documentation cache and avoid
|
40
43
|
# generating the documentation on runtime (usefull for production
|
41
44
|
# environment).
|
@@ -124,6 +127,9 @@ module Apipie
|
|
124
127
|
@version_in_url = true
|
125
128
|
@namespaced_resources = false
|
126
129
|
@doc_path = "doc"
|
130
|
+
@process_params = false
|
131
|
+
@checksum_path = [@doc_base_url, '/api/']
|
132
|
+
@update_checksum = false
|
127
133
|
end
|
128
134
|
end
|
129
135
|
end
|
@@ -6,7 +6,7 @@ module Apipie
|
|
6
6
|
module DSL
|
7
7
|
|
8
8
|
module Base
|
9
|
-
attr_reader :apipie_resource_descriptions
|
9
|
+
attr_reader :apipie_resource_descriptions, :api_params
|
10
10
|
|
11
11
|
private
|
12
12
|
|
@@ -29,7 +29,8 @@ module Apipie
|
|
29
29
|
:examples => [],
|
30
30
|
:see => [],
|
31
31
|
:formats => nil,
|
32
|
-
:api_versions => []
|
32
|
+
:api_versions => [],
|
33
|
+
:meta => nil
|
33
34
|
}
|
34
35
|
end
|
35
36
|
end
|
@@ -76,7 +77,7 @@ module Apipie
|
|
76
77
|
# Example:
|
77
78
|
# api :GET, "/resource_route", "short description",
|
78
79
|
#
|
79
|
-
def api(method, path, desc = nil) #:doc:
|
80
|
+
def api(method, path, desc = nil, options={}) #:doc:
|
80
81
|
return unless Apipie.active_dsl?
|
81
82
|
_apipie_dsl_data[:api_args] << [method, path, desc]
|
82
83
|
end
|
@@ -164,20 +165,27 @@ module Apipie
|
|
164
165
|
_apipie_dsl_data[:formats] = formats
|
165
166
|
end
|
166
167
|
|
168
|
+
# Describe additional metadata
|
169
|
+
#
|
170
|
+
# meta :author => { :name => 'John', :surname => 'Doe' }
|
171
|
+
def meta(meta) #:doc:
|
172
|
+
_apipie_dsl_data[:meta] = meta
|
173
|
+
end
|
174
|
+
|
167
175
|
|
168
176
|
# Describe possible errors
|
169
177
|
#
|
170
178
|
# Example:
|
171
|
-
# error :desc => "speaker is sleeping", :code => 500
|
179
|
+
# error :desc => "speaker is sleeping", :code => 500, :meta => [:some, :more, :data]
|
172
180
|
# error 500, "speaker is sleeping"
|
173
181
|
# def hello_world
|
174
182
|
# return 500 if self.speaker.sleeping?
|
175
183
|
# puts "hello world"
|
176
184
|
# end
|
177
185
|
#
|
178
|
-
def error(
|
186
|
+
def error(code_or_options, desc=nil, options={}) #:doc:
|
179
187
|
return unless Apipie.active_dsl?
|
180
|
-
_apipie_dsl_data[:errors] <<
|
188
|
+
_apipie_dsl_data[:errors] << [code_or_options, desc, options]
|
181
189
|
end
|
182
190
|
|
183
191
|
def _apipie_define_validators(description)
|
@@ -186,6 +194,8 @@ module Apipie
|
|
186
194
|
|
187
195
|
old_method = instance_method(description.method)
|
188
196
|
|
197
|
+
|
198
|
+
# @todo we should use before_filter
|
189
199
|
define_method(description.method) do |*args|
|
190
200
|
|
191
201
|
if Apipie.configuration.validate_presence?
|
@@ -202,6 +212,15 @@ module Apipie
|
|
202
212
|
end
|
203
213
|
end
|
204
214
|
|
215
|
+
if Apipie.configuration.process_value?
|
216
|
+
@api_params = {}
|
217
|
+
|
218
|
+
description.params.each do |_, param|
|
219
|
+
# params processing
|
220
|
+
@api_params[param.as] = param.process_value(params[:"#{param.name}"]) if params.has_key?(param.name)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
205
224
|
# run the original method code
|
206
225
|
old_method.bind(self).call(*args)
|
207
226
|
end
|
@@ -2,22 +2,34 @@ module Apipie
|
|
2
2
|
|
3
3
|
class ErrorDescription
|
4
4
|
|
5
|
-
attr_reader :code, :description
|
5
|
+
attr_reader :code, :description, :metadata
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
def self.from_dsl_data(args)
|
8
|
+
code_or_options, desc, options = args
|
9
|
+
Apipie::ErrorDescription.new(code_or_options,
|
10
|
+
desc,
|
11
|
+
options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(code_or_options, desc=nil, options={})
|
15
|
+
if code_or_options.is_a? Hash
|
16
|
+
code_or_options.symbolize_keys!
|
17
|
+
@code = code_or_options[:code]
|
18
|
+
@metadata = code_or_options[:meta]
|
19
|
+
@description = code_or_options[:desc] || code_or_options[:description]
|
12
20
|
else
|
13
|
-
|
21
|
+
@code = code_or_options
|
22
|
+
@metadata = options[:meta]
|
23
|
+
@description = desc
|
14
24
|
end
|
15
|
-
@code = args[:code] || args['code']
|
16
|
-
@description = args[:desc] || args[:description] || args['desc'] || args['description']
|
17
25
|
end
|
18
26
|
|
19
27
|
def to_json
|
20
|
-
{
|
28
|
+
{
|
29
|
+
:code => code,
|
30
|
+
:description => description,
|
31
|
+
:metadata => metadata
|
32
|
+
}
|
21
33
|
end
|
22
34
|
|
23
35
|
end
|
data/lib/apipie/extractor.rb
CHANGED
@@ -86,7 +86,8 @@ module Apipie
|
|
86
86
|
controller_path, action = route[:controller], route[:action]
|
87
87
|
next unless controller_path && action
|
88
88
|
|
89
|
-
|
89
|
+
controller_path = controller_path.split('::').map(&:camelize).join('::')
|
90
|
+
controller = "#{controller_path}Controller"
|
90
91
|
|
91
92
|
path = if /^#{Regexp.escape(api_prefix)}(.*)$/ =~ route[:path]
|
92
93
|
$1.sub!(/\(\.:format\)$/,"")
|
@@ -84,7 +84,9 @@ module Apipie
|
|
84
84
|
method_descriptions = Apipie.get_method_descriptions(call[:controller], call[:action])
|
85
85
|
call[:versions] = method_descriptions.map(&:version)
|
86
86
|
|
87
|
-
if
|
87
|
+
if Apipie.configuration.show_all_examples
|
88
|
+
show_in_doc = 1
|
89
|
+
elsif call[:versions].any? { |v| ! showed_in_versions.include?(v) }
|
88
90
|
call[:versions].each { |v| showed_in_versions << v }
|
89
91
|
show_in_doc = 1
|
90
92
|
else
|
@@ -99,11 +101,11 @@ module Apipie
|
|
99
101
|
|
100
102
|
def load_old_examples
|
101
103
|
if File.exists?(@examples_file)
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
if defined? SafeYAML
|
105
|
+
return YAML.load_file(@examples_file, :safe=>false)
|
106
|
+
else
|
107
|
+
return YAML.load_file(@examples_file)
|
108
|
+
end
|
107
109
|
end
|
108
110
|
return {}
|
109
111
|
end
|