apipie-rails 0.1.3 → 0.2.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/.travis.yml +1 -2
- data/CHANGELOG.md +26 -0
- data/README.rst +94 -3
- data/app/controllers/apipie/apipies_controller.rb +28 -10
- data/app/views/apipie/apipies/_disqus.html.erb +4 -2
- data/app/views/apipie/apipies/_languages.erb +6 -0
- data/app/views/apipie/apipies/_method_detail.erb +7 -7
- data/app/views/apipie/apipies/_params.html.erb +2 -2
- data/app/views/apipie/apipies/_params_plain.html.erb +2 -2
- data/app/views/apipie/apipies/apipie_404.html.erb +7 -4
- data/app/views/apipie/apipies/getting_started.html.erb +5 -3
- data/app/views/apipie/apipies/index.html.erb +7 -6
- data/app/views/apipie/apipies/method.html.erb +4 -2
- data/app/views/apipie/apipies/plain.html.erb +3 -3
- data/app/views/apipie/apipies/resource.html.erb +3 -2
- data/app/views/apipie/apipies/static.html.erb +7 -7
- data/app/views/layouts/apipie/apipie.html.erb +1 -1
- data/config/locales/en.yml +27 -0
- data/lib/apipie-rails.rb +7 -0
- data/lib/apipie/apipie_module.rb +5 -2
- data/lib/apipie/application.rb +27 -16
- data/lib/apipie/configuration.rb +6 -1
- data/lib/apipie/extractor.rb +35 -26
- data/lib/apipie/extractor/recorder.rb +9 -5
- data/lib/apipie/extractor/writer.rb +36 -7
- data/lib/apipie/method_description.rb +6 -6
- data/lib/apipie/param_description.rb +9 -4
- data/lib/apipie/resource_description.rb +5 -5
- data/lib/apipie/routing.rb +1 -1
- data/lib/apipie/version.rb +1 -1
- data/lib/generators/apipie/install/templates/initializer.rb.erb +1 -1
- data/lib/tasks/apipie.rake +89 -47
- data/spec/dummy/doc/apipie_examples.json +1 -0
- data/spec/lib/extractor/middleware_spec.rb +21 -0
- data/spec/lib/extractor/writer_spec.rb +76 -0
- metadata +10 -5
- data/Gemfile.rails30 +0 -5
- data/spec/dummy/doc/apipie_examples.yml +0 -28
@@ -7,6 +7,7 @@
|
|
7
7
|
<%= @resource[:name] %>
|
8
8
|
<% if @resource[:version] %><% end %>
|
9
9
|
</li>
|
10
|
+
<%= render(:partial => "languages", :locals => {:doc_url => @resource[:doc_url]}) %>
|
10
11
|
</ul>
|
11
12
|
|
12
13
|
<div class='page-header'>
|
@@ -62,6 +63,6 @@
|
|
62
63
|
<% end %>
|
63
64
|
</div>
|
64
65
|
|
65
|
-
<% content_for
|
66
|
-
<%= raw
|
66
|
+
<% unless content_for(:apipie_footer) == @doc[:copyright] %>
|
67
|
+
<%= content_for :apipie_footer, raw(@doc[:copyright]) %>
|
67
68
|
<% end %>
|
@@ -62,14 +62,14 @@
|
|
62
62
|
<div>
|
63
63
|
<%= raw method[:full_description] %>
|
64
64
|
<% unless method[:examples].blank? %>
|
65
|
-
<h2
|
65
|
+
<h2><%= t('apipie.examples') %></h2>
|
66
66
|
<% method[:examples].each do |example| %>
|
67
67
|
<pre><%= example %></pre>
|
68
68
|
<% end %>
|
69
69
|
<% end %>
|
70
70
|
|
71
71
|
<% unless method[:errors].blank? %>
|
72
|
-
<h2
|
72
|
+
<h2><%= t('apipie.errors') %></h2>
|
73
73
|
<% method[:errors].each do |err| %>
|
74
74
|
<%= err[:code] %>
|
75
75
|
<%= err[:description] %>
|
@@ -79,12 +79,12 @@
|
|
79
79
|
<% end %>
|
80
80
|
|
81
81
|
<% unless method[:params].blank? %>
|
82
|
-
<h2
|
82
|
+
<h2><%= t('apipie.params') %></h2>
|
83
83
|
<table class='table'>
|
84
84
|
<thead>
|
85
85
|
<tr>
|
86
|
-
<th
|
87
|
-
<th
|
86
|
+
<th><%= t('apipie.param_name') %></th>
|
87
|
+
<th><%= t('apipie.description') %></th>
|
88
88
|
</tr>
|
89
89
|
</thead>
|
90
90
|
<tbody>
|
@@ -97,6 +97,6 @@
|
|
97
97
|
</div>
|
98
98
|
<% end %>
|
99
99
|
|
100
|
-
<% content_for
|
101
|
-
<%= raw
|
100
|
+
<% unless content_for(:apipie_footer) == @doc[:copyright] %>
|
101
|
+
<%= content_for :apipie_footer, raw(@doc[:copyright]) %>
|
102
102
|
<% end %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html>
|
3
3
|
<head>
|
4
|
-
<title
|
4
|
+
<title><%= t('apipie.api_documentation') %></title>
|
5
5
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
6
6
|
<%= Apipie.include_stylesheets %>
|
7
7
|
<link type='text/css' rel='stylesheet' href='<%= Apipie.full_url("stylesheets/application.css")%>'/>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
en:
|
2
|
+
apipie:
|
3
|
+
resources: Resources
|
4
|
+
resource: Resource
|
5
|
+
description: Description
|
6
|
+
no_docs_found: No documentation found
|
7
|
+
no_docs_found_descr: We have not found any documentation for your API.
|
8
|
+
follow_instructions_html: Follow %{href} on how to describe your controllers.
|
9
|
+
follow_instructions_href: further instructions
|
10
|
+
oops: Oops!!
|
11
|
+
resource_not_found_html: Resource %{res} not found.
|
12
|
+
method_not_found_html: Method %{method} not found for resource %{resource}.
|
13
|
+
goto_homepage_html: Try going to %{href}
|
14
|
+
goto_homepage_href: "%{app_name} API documentation homepage"
|
15
|
+
required: required
|
16
|
+
optional: optional
|
17
|
+
nil_allowed: nil allowed
|
18
|
+
param_name: Param name
|
19
|
+
params: Params
|
20
|
+
examples: Examples
|
21
|
+
metadata: Metadata
|
22
|
+
errors: Errors
|
23
|
+
supported_formats: Supported Formats
|
24
|
+
enable_javascript_html: Please enable JavaScript to view the %{comments_href}.
|
25
|
+
comments_powered_by_disqus: comments powered by %{disqus}
|
26
|
+
api_documentation: API documentation
|
27
|
+
|
data/lib/apipie-rails.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
|
1
4
|
require "apipie/routing"
|
2
5
|
require "apipie/markup"
|
3
6
|
require "apipie/apipie_module"
|
@@ -13,3 +16,7 @@ require "apipie/validator"
|
|
13
16
|
require "apipie/railtie"
|
14
17
|
require 'apipie/extractor'
|
15
18
|
require "apipie/version"
|
19
|
+
|
20
|
+
if Rails.version.start_with?("3.0")
|
21
|
+
warn 'Warning: apipie-rails is not going to support Rails 3.0 anymore in future versions'
|
22
|
+
end
|
data/lib/apipie/apipie_module.rb
CHANGED
@@ -8,9 +8,9 @@ module Apipie
|
|
8
8
|
@application ||= Apipie::Application.new
|
9
9
|
end
|
10
10
|
|
11
|
-
def self.to_json(version = nil, resource_name = nil, method_name = nil)
|
11
|
+
def self.to_json(version = nil, resource_name = nil, method_name = nil, lang = nil)
|
12
12
|
version ||= Apipie.configuration.default_version
|
13
|
-
app.to_json(version, resource_name, method_name)
|
13
|
+
app.to_json(version, resource_name, method_name, lang)
|
14
14
|
end
|
15
15
|
|
16
16
|
# all calls delegated to Apipie::Application instance
|
@@ -59,4 +59,7 @@ module Apipie
|
|
59
59
|
version && self.configuration.api_base_url.has_key?(version)
|
60
60
|
end
|
61
61
|
|
62
|
+
def self.record(record)
|
63
|
+
Apipie::Extractor.start record
|
64
|
+
end
|
62
65
|
end
|
data/lib/apipie/application.rb
CHANGED
@@ -207,25 +207,14 @@ module Apipie
|
|
207
207
|
|
208
208
|
def recorded_examples
|
209
209
|
return @recorded_examples if @recorded_examples
|
210
|
-
|
211
|
-
if File.exists?(tape_file)
|
212
|
-
#if SafeYAML gem is enabled, it will load examples as an array of Hash, instead of hash
|
213
|
-
if YAML.respond_to?(:safe_load_file) && defined?(SafeYAML)
|
214
|
-
@recorded_examples = YAML.load_file(tape_file, :safe=>false)
|
215
|
-
else
|
216
|
-
@recorded_examples = YAML.load_file(tape_file)
|
217
|
-
end
|
218
|
-
else
|
219
|
-
@recorded_examples = {}
|
220
|
-
end
|
221
|
-
@recorded_examples
|
210
|
+
@recorded_examples = Apipie::Extractor::Writer.load_recorded_examples
|
222
211
|
end
|
223
212
|
|
224
213
|
def reload_examples
|
225
214
|
@recorded_examples = nil
|
226
215
|
end
|
227
216
|
|
228
|
-
def to_json(version, resource_name, method_name)
|
217
|
+
def to_json(version, resource_name, method_name, lang)
|
229
218
|
|
230
219
|
return unless resource_descriptions.has_key?(version)
|
231
220
|
|
@@ -233,11 +222,11 @@ module Apipie
|
|
233
222
|
# take just resources which have some methods because
|
234
223
|
# we dont want to show eg ApplicationController as resource
|
235
224
|
resource_descriptions[version].inject({}) do |result, (k,v)|
|
236
|
-
result[k] = v.to_json unless v._methods.blank?
|
225
|
+
result[k] = v.to_json(nil, lang) unless v._methods.blank?
|
237
226
|
result
|
238
227
|
end
|
239
228
|
else
|
240
|
-
[@resource_descriptions[version][resource_name].to_json(method_name)]
|
229
|
+
[@resource_descriptions[version][resource_name].to_json(method_name, lang)]
|
241
230
|
end
|
242
231
|
|
243
232
|
url_args = Apipie.configuration.version_in_url ? version : ''
|
@@ -245,7 +234,7 @@ module Apipie
|
|
245
234
|
{
|
246
235
|
:docs => {
|
247
236
|
:name => Apipie.configuration.app_name,
|
248
|
-
:info => Apipie.app_info(version),
|
237
|
+
:info => translate(Apipie.app_info(version), lang),
|
249
238
|
:copyright => Apipie.configuration.copyright,
|
250
239
|
:doc_url => Apipie.full_url(url_args),
|
251
240
|
:api_url => Apipie.api_base_url(version),
|
@@ -259,12 +248,18 @@ module Apipie
|
|
259
248
|
end
|
260
249
|
|
261
250
|
def reload_documentation
|
251
|
+
# don't load translated strings, we'll translate them later
|
252
|
+
old_locale = locale
|
253
|
+
locale = Apipie.configuration.default_locale
|
254
|
+
|
262
255
|
rails_mark_classes_for_reload
|
263
256
|
|
264
257
|
api_controllers_paths.each do |f|
|
265
258
|
load_controller_from_file f
|
266
259
|
end
|
267
260
|
@checksum = nil if Apipie.configuration.update_checksum
|
261
|
+
|
262
|
+
locale = old_locale
|
268
263
|
end
|
269
264
|
|
270
265
|
def compute_checksum
|
@@ -311,6 +306,22 @@ module Apipie
|
|
311
306
|
end
|
312
307
|
end
|
313
308
|
|
309
|
+
def locale
|
310
|
+
Apipie.configuration.locale.call(nil) if Apipie.configuration.locale
|
311
|
+
end
|
312
|
+
|
313
|
+
def locale=(locale)
|
314
|
+
Apipie.configuration.locale.call(locale) if Apipie.configuration.locale
|
315
|
+
end
|
316
|
+
|
317
|
+
def translate(str, locale)
|
318
|
+
if Apipie.configuration.translate
|
319
|
+
Apipie.configuration.translate.call(str, locale)
|
320
|
+
else
|
321
|
+
str
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
314
325
|
private
|
315
326
|
|
316
327
|
def version_prefix(klass)
|
data/lib/apipie/configuration.rb
CHANGED
@@ -6,7 +6,7 @@ module Apipie
|
|
6
6
|
:default_version, :debug, :version_in_url, :namespaced_resources,
|
7
7
|
:validate, :validate_value, :validate_presence, :authenticate, :doc_path,
|
8
8
|
:show_all_examples, :process_params, :update_checksum, :checksum_path,
|
9
|
-
:link_extension
|
9
|
+
:link_extension, :record, :languages, :translate, :locale, :default_locale
|
10
10
|
|
11
11
|
alias_method :validate?, :validate
|
12
12
|
alias_method :required_by_default?, :required_by_default
|
@@ -141,6 +141,11 @@ module Apipie
|
|
141
141
|
@checksum_path = [@doc_base_url, '/api/']
|
142
142
|
@update_checksum = false
|
143
143
|
@link_extension = ".html"
|
144
|
+
@record = false
|
145
|
+
@languages = []
|
146
|
+
@default_locale = 'en'
|
147
|
+
@locale = lambda { |locale| @default_locale }
|
148
|
+
@translate = lambda { |str, locale| str }
|
144
149
|
end
|
145
150
|
end
|
146
151
|
end
|
data/lib/apipie/extractor.rb
CHANGED
@@ -7,17 +7,17 @@ require 'apipie/extractor/writer'
|
|
7
7
|
require 'apipie/extractor/collector'
|
8
8
|
|
9
9
|
class Apipie::Railtie
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
initializer 'apipie.extractor' do |app|
|
11
|
+
ActiveSupport.on_load :action_controller do
|
12
|
+
before_filter do |controller|
|
13
|
+
if Apipie.configuration.record
|
14
14
|
Apipie::Extractor.call_recorder.analyse_controller(controller)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
end
|
18
|
+
app.middleware.use ::Apipie::Extractor::Recorder::Middleware
|
19
|
+
ActionController::TestCase::Behavior.instance_eval do
|
20
|
+
include Apipie::Extractor::Recorder::FunctionalTestRecording
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -28,6 +28,29 @@ module Apipie
|
|
28
28
|
|
29
29
|
class << self
|
30
30
|
|
31
|
+
def start(record)
|
32
|
+
Apipie.configuration.record = record
|
33
|
+
Apipie.configuration.force_dsl = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def finish
|
37
|
+
record_params, record_examples = false, false
|
38
|
+
case Apipie.configuration.record
|
39
|
+
when "params" then record_params = true
|
40
|
+
when "examples" then record_examples = true
|
41
|
+
when "all" then record_params = true, record_examples = true
|
42
|
+
end
|
43
|
+
|
44
|
+
if record_examples
|
45
|
+
puts "Writing examples to a file"
|
46
|
+
write_examples
|
47
|
+
end
|
48
|
+
if record_params
|
49
|
+
puts "Updating auto-generated documentation"
|
50
|
+
write_docs
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
31
54
|
def logger
|
32
55
|
Rails.logger
|
33
56
|
end
|
@@ -144,28 +167,14 @@ module Apipie
|
|
144
167
|
end
|
145
168
|
end
|
146
169
|
end
|
147
|
-
|
148
170
|
end
|
149
171
|
end
|
150
172
|
end
|
151
173
|
|
152
174
|
if ENV["APIPIE_RECORD"]
|
153
|
-
Apipie.
|
154
|
-
|
155
|
-
record_params, record_examples = false, false
|
156
|
-
case ENV["APIPIE_RECORD"]
|
157
|
-
when "params" then record_params = true
|
158
|
-
when "examples" then record_examples = true
|
159
|
-
when "all" then record_params = true, record_examples = true
|
160
|
-
end
|
175
|
+
Apipie::Extractor.start ENV["APIPIE_RECORD"]
|
176
|
+
end
|
161
177
|
|
162
|
-
|
163
|
-
|
164
|
-
Apipie::Extractor.write_examples
|
165
|
-
end
|
166
|
-
if record_params
|
167
|
-
puts "Updating auto-generated documentation"
|
168
|
-
Apipie::Extractor.write_docs
|
169
|
-
end
|
170
|
-
end
|
178
|
+
at_exit do
|
179
|
+
Apipie::Extractor.finish
|
171
180
|
end
|
@@ -89,7 +89,11 @@ module Apipie
|
|
89
89
|
end
|
90
90
|
|
91
91
|
def call(env)
|
92
|
-
|
92
|
+
if Apipie.configuration.record
|
93
|
+
analyze(env) do
|
94
|
+
@app.call(env)
|
95
|
+
end
|
96
|
+
else
|
93
97
|
@app.call(env)
|
94
98
|
end
|
95
99
|
end
|
@@ -112,15 +116,15 @@ module Apipie
|
|
112
116
|
|
113
117
|
def process_with_api_recording(*args) # action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
|
114
118
|
ret = process_without_api_recording(*args)
|
115
|
-
Apipie
|
116
|
-
|
119
|
+
if Apipie.configuration.record
|
120
|
+
Apipie::Extractor.call_recorder.analyze_functional_test(self)
|
121
|
+
Apipie::Extractor.call_finished
|
122
|
+
end
|
117
123
|
ret
|
118
124
|
ensure
|
119
125
|
Apipie::Extractor.clean_call_recorder
|
120
126
|
end
|
121
127
|
end
|
122
|
-
|
123
128
|
end
|
124
|
-
|
125
129
|
end
|
126
130
|
end
|
@@ -6,15 +6,11 @@ module Apipie
|
|
6
6
|
|
7
7
|
def initialize(collector)
|
8
8
|
@collector = collector
|
9
|
-
@examples_file = File.join(Rails.root, "doc", "apipie_examples.yml")
|
10
9
|
end
|
11
10
|
|
12
11
|
def write_examples
|
13
12
|
merged_examples = merge_old_new_examples
|
14
|
-
|
15
|
-
File.open(@examples_file, "w") do |f|
|
16
|
-
f << YAML.dump(OrderedHash[*merged_examples.sort_by(&:first).flatten(1)])
|
17
|
-
end
|
13
|
+
self.class.write_recorded_examples(merged_examples)
|
18
14
|
end
|
19
15
|
|
20
16
|
def write_docs
|
@@ -40,8 +36,38 @@ module Apipie
|
|
40
36
|
logger.warn("REST_API: Couldn't find action #{action} in #{controller}")
|
41
37
|
end
|
42
38
|
|
39
|
+
def self.write_recorded_examples(examples)
|
40
|
+
examples_file = self.examples_file
|
41
|
+
FileUtils.mkdir_p(File.dirname(examples_file))
|
42
|
+
File.open(examples_file, "w") do |f|
|
43
|
+
f << JSON.pretty_generate(OrderedHash[*examples.sort_by(&:first).flatten(1)])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.load_recorded_examples
|
48
|
+
examples_file = self.examples_file
|
49
|
+
if File.exists?(examples_file)
|
50
|
+
return load_json_examples
|
51
|
+
end
|
52
|
+
return {}
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.examples_file
|
56
|
+
File.join(Rails.root,"doc","apipie_examples.json")
|
57
|
+
end
|
58
|
+
|
43
59
|
protected
|
44
60
|
|
61
|
+
def self.load_json_examples
|
62
|
+
examples = JSON.load(IO.read(examples_file))
|
63
|
+
return {} if examples.nil?
|
64
|
+
examples.each do |method, records|
|
65
|
+
records.each do |record|
|
66
|
+
record["verb"] = record["verb"].to_sym if record["verb"]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
45
71
|
def desc_to_s(description)
|
46
72
|
"#{description[:controller].name}##{description[:action]}"
|
47
73
|
end
|
@@ -61,9 +87,13 @@ module Apipie
|
|
61
87
|
return ordered_call
|
62
88
|
end
|
63
89
|
|
90
|
+
def load_recorded_examples
|
91
|
+
self.class.load_recorded_examples
|
92
|
+
end
|
93
|
+
|
64
94
|
def merge_old_new_examples
|
65
95
|
new_examples = self.load_new_examples
|
66
|
-
old_examples = self.
|
96
|
+
old_examples = self.load_recorded_examples
|
67
97
|
merged_examples = []
|
68
98
|
(new_examples.keys + old_examples.keys).uniq.each do |key|
|
69
99
|
if new_examples.has_key?(key)
|
@@ -364,6 +394,5 @@ module Apipie
|
|
364
394
|
end
|
365
395
|
end
|
366
396
|
end
|
367
|
-
|
368
397
|
end
|
369
398
|
end
|
@@ -108,12 +108,12 @@ module Apipie
|
|
108
108
|
return path
|
109
109
|
end
|
110
110
|
|
111
|
-
def method_apis_to_json
|
111
|
+
def method_apis_to_json(lang = nil)
|
112
112
|
@apis.each.collect do |api|
|
113
113
|
{
|
114
114
|
:api_url => create_api_url(api),
|
115
115
|
:http_method => api.http_method.to_s,
|
116
|
-
:short_description => api.short_description
|
116
|
+
:short_description => Apipie.app.translate(api.short_description, lang)
|
117
117
|
}
|
118
118
|
end
|
119
119
|
end
|
@@ -126,15 +126,15 @@ module Apipie
|
|
126
126
|
@formats || @resource._formats
|
127
127
|
end
|
128
128
|
|
129
|
-
def to_json
|
129
|
+
def to_json(lang=nil)
|
130
130
|
{
|
131
131
|
:doc_url => doc_url,
|
132
132
|
:name => @method,
|
133
|
-
:apis => method_apis_to_json,
|
133
|
+
:apis => method_apis_to_json(lang),
|
134
134
|
:formats => formats,
|
135
|
-
:full_description => @full_description,
|
135
|
+
:full_description => Apipie.app.translate(@full_description, lang),
|
136
136
|
:errors => errors.map(&:to_json),
|
137
|
-
:params => params_ordered.map(
|
137
|
+
:params => params_ordered.map{ |param| param.to_json(lang) }.flatten,
|
138
138
|
:examples => @examples,
|
139
139
|
:metadata => @metadata,
|
140
140
|
:see => see.map(&:to_json)
|