apipie-rails 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,30 @@
|
|
2
2
|
Changelog
|
3
3
|
===========
|
4
4
|
|
5
|
+
v0.2.0
|
6
|
+
------
|
7
|
+
|
8
|
+
This is not full backward compatible release, as the format of storing
|
9
|
+
examples changed from YAML to JSON: the default location is at
|
10
|
+
`doc/apipie_examples.json`. The migration should be as easy as
|
11
|
+
running:
|
12
|
+
|
13
|
+
```
|
14
|
+
rake apipie:convert_examples
|
15
|
+
```
|
16
|
+
|
17
|
+
Also please not Rails 3.0 support was deprecated and the compatibility
|
18
|
+
wont be tracked anymore in next releases.
|
19
|
+
|
20
|
+
* dump examples as json
|
21
|
+
[#125](https://github.com/Apipie/apipie-rails/pull/125) [@johanneswuerbach][]
|
22
|
+
* support for localized API documentation
|
23
|
+
[#232](https://github.com/Apipie/apipie-rails/pull/232) [@mbacovsky][]
|
24
|
+
* configuration option to always record examples
|
25
|
+
[#239](https://github.com/Apipie/apipie-rails/pull/239) [@arathunku][]
|
26
|
+
* deprecate Rails 3.0
|
27
|
+
[#241](https://github.com/Apipie/apipie-rails/pull/241) [@iNecas][]
|
28
|
+
|
5
29
|
v0.1.3
|
6
30
|
------
|
7
31
|
|
@@ -119,3 +143,5 @@ v0.0.15
|
|
119
143
|
[@mkrajewski]: https://github.com/mkrajewski
|
120
144
|
[@iNecas]: https://github.com/iNecas
|
121
145
|
[@clamoris]: https://github.com/clamoris
|
146
|
+
[@arathunku]: https://github.com/arathunku
|
147
|
+
[@johanneswuerbach]: https://github.com/johanneswuerbach
|
data/README.rst
CHANGED
@@ -554,7 +554,25 @@ show_all_examples
|
|
554
554
|
|
555
555
|
link_extension
|
556
556
|
The extension to use for API pages ('.html' by default). Link extensions
|
557
|
-
in static API docs cannot be changed from '.html'.
|
557
|
+
in static API docs cannot be changed from '.html'.
|
558
|
+
|
559
|
+
languages
|
560
|
+
List of languages API documentation should be translated into. Empty list by default.
|
561
|
+
|
562
|
+
default_locale
|
563
|
+
Locale used for generating documentation when no specific locale is set.
|
564
|
+
Set to 'en' by default.
|
565
|
+
|
566
|
+
locale
|
567
|
+
Pass locale setter/getter
|
568
|
+
|
569
|
+
.. code:: ruby
|
570
|
+
|
571
|
+
config.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }
|
572
|
+
|
573
|
+
translate
|
574
|
+
Pass proc to translate strings using localization library your project uses.
|
575
|
+
For example see `Localization`_
|
558
576
|
|
559
577
|
Example:
|
560
578
|
|
@@ -863,6 +881,79 @@ For inspiration this is how Textile markup usage looks like:
|
|
863
881
|
end
|
864
882
|
end
|
865
883
|
|
884
|
+
============
|
885
|
+
Localization
|
886
|
+
============
|
887
|
+
|
888
|
+
Apipie has support for localized API documentation in both formats (JSON and HTML).
|
889
|
+
Apipie uses the library I18n for localization of itself.
|
890
|
+
Check ``config/locales`` directory for available translation.
|
891
|
+
|
892
|
+
Major part of strings in the documentation comes from the API.
|
893
|
+
As prefferences about localization libraries differs among project, Apipie needs to know how to set locale for your project
|
894
|
+
and how to translate a string using library your project use. That can be done using lambdas in configuration.
|
895
|
+
|
896
|
+
Sample configuration when your project use FastGettext
|
897
|
+
|
898
|
+
|
899
|
+
.. code:: ruby
|
900
|
+
|
901
|
+
Apipie.configure do |config|
|
902
|
+
...
|
903
|
+
config.languages = ['en', 'cs']
|
904
|
+
config.default_locale = 'en'
|
905
|
+
config.locale = lambda { |loc| loc ? FastGettext.set_locale(loc) : FastGettext.locale }
|
906
|
+
config.translate = lambda do |str, loc|
|
907
|
+
old_loc = FastGettext.locale
|
908
|
+
FastGettext.set_locale(loc)
|
909
|
+
trans = _(str)
|
910
|
+
FastGettext.set_locale(old_loc)
|
911
|
+
trans
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
915
|
+
And the strings in API documentation needs to be marked with the ``N_()`` function
|
916
|
+
|
917
|
+
.. code:: ruby
|
918
|
+
|
919
|
+
api :GET, "/users/:id", N_("Show user profile")
|
920
|
+
param :session, String, :desc => N_("user is logged in"), :required => true
|
921
|
+
|
922
|
+
|
923
|
+
|
924
|
+
When your project use I18n, localization related configuration could look like as follows
|
925
|
+
|
926
|
+
.. code:: ruby
|
927
|
+
|
928
|
+
Apipie.configure do |config|
|
929
|
+
...
|
930
|
+
config.languages = ['en', 'cs']
|
931
|
+
config.default_locale = 'en'
|
932
|
+
config.locale = lambda { |loc| loc ? I18n.locale = loc : I18n.locale }
|
933
|
+
config.translate = lambda do |str, loc|
|
934
|
+
old_loc = I18n.locale
|
935
|
+
I18n.locale = loc
|
936
|
+
trans = I18n.t(str)
|
937
|
+
I18n.locale = old_loc
|
938
|
+
trans
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
942
|
+
And the strings in API documentation needs to be in the form of translation keys
|
943
|
+
|
944
|
+
.. code:: ruby
|
945
|
+
|
946
|
+
api :GET, "/users/:id", "show_user_profile"
|
947
|
+
param :session, String, :desc => "user_is_logged_in", :required => true
|
948
|
+
|
949
|
+
|
950
|
+
The localized versions of the documentation are distinguished by languge in the filename.
|
951
|
+
E.g. ``doc/apidoc/apidoc.cs.html`` is static documentation in the Czech language.
|
952
|
+
If the language is missing, e.g. ``doc/apidoc/apidoc.html``,
|
953
|
+
the documentation is localized with the ``default_locale``.
|
954
|
+
|
955
|
+
The dynamic documentation follows the same schema. The ``http://localhost:3000/apidoc/v1.cs.html`` is documentation for version '1' of the API in the Czech language. For JSON description of the API applies the same: ``http://localhost:3000/apidoc/v1.cs.json``
|
956
|
+
|
866
957
|
|
867
958
|
================
|
868
959
|
Modifying Views
|
@@ -940,7 +1031,7 @@ of information is already included in this tests, it just needs to be
|
|
940
1031
|
extracted somehow. Luckily, Apipie provides such a feature.
|
941
1032
|
|
942
1033
|
When running the tests, set the ``APIPIE_RECORD=params`` environment
|
943
|
-
variable. You can either use it with functional tests
|
1034
|
+
variable or call ``Apipie.record('params')`` from specs starter. You can either use it with functional tests
|
944
1035
|
|
945
1036
|
.. code::
|
946
1037
|
|
@@ -962,7 +1053,7 @@ Examples Recording
|
|
962
1053
|
|
963
1054
|
You can also use the tests to generate up-to-date examples for your
|
964
1055
|
code. Similarly to the bootstrapping, you can use it with functional
|
965
|
-
tests or a running server, setting ``APIPIE_RECORD=examples``
|
1056
|
+
tests or a running server, setting ``APIPIE_RECORD=examples`` or by calling ``Apipie.record('examples')`` in your specs starter.
|
966
1057
|
|
967
1058
|
.. code::
|
968
1059
|
|
@@ -24,8 +24,11 @@ module Apipie
|
|
24
24
|
return
|
25
25
|
end
|
26
26
|
|
27
|
+
@language = get_language
|
28
|
+
|
27
29
|
Apipie.reload_documentation if Apipie.configuration.reload_controllers?
|
28
|
-
|
30
|
+
I18n.locale = @language
|
31
|
+
@doc = Apipie.to_json(params[:version], params[:resource], params[:method], @language)
|
29
32
|
|
30
33
|
format.json do
|
31
34
|
if @doc
|
@@ -43,12 +46,13 @@ module Apipie
|
|
43
46
|
|
44
47
|
@versions = Apipie.available_versions
|
45
48
|
@doc = @doc[:docs]
|
46
|
-
@doc[:link_extension] = Apipie.configuration.link_extension
|
49
|
+
@doc[:link_extension] = (@language ? ".#{@language}" : '')+Apipie.configuration.link_extension
|
47
50
|
if @doc[:resources].blank?
|
48
51
|
render "getting_started" and return
|
49
52
|
end
|
50
53
|
@resource = @doc[:resources].first if params[:resource].present?
|
51
54
|
@method = @resource[:methods].first if params[:method].present?
|
55
|
+
@languages = Apipie.configuration.languages
|
52
56
|
|
53
57
|
if @resource && @method
|
54
58
|
render 'method'
|
@@ -68,20 +72,34 @@ module Apipie
|
|
68
72
|
|
69
73
|
private
|
70
74
|
|
75
|
+
def get_language
|
76
|
+
lang = nil
|
77
|
+
[:resource, :method, :version].each do |par|
|
78
|
+
if params[par]
|
79
|
+
splitted = params[par].split('.')
|
80
|
+
if splitted.length > 1 && Apipie.configuration.languages.include?(splitted.last)
|
81
|
+
lang = splitted.last
|
82
|
+
params[par].sub!(".#{lang}", '')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
lang
|
87
|
+
end
|
88
|
+
|
71
89
|
def get_format
|
72
|
-
|
73
|
-
|
90
|
+
[:resource, :method, :version].each do |par|
|
91
|
+
if params[par]
|
92
|
+
params[:format] = :html unless params[par].sub!('.html', '').nil?
|
93
|
+
params[:format] = :json unless params[par].sub!('.json', '').nil?
|
94
|
+
end
|
95
|
+
end
|
74
96
|
request.format = params[:format] if params[:format]
|
75
97
|
end
|
76
98
|
|
77
99
|
def render_from_cache
|
78
100
|
path = Apipie.configuration.doc_base_url.dup
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
# version can contain dot, but only one in row
|
83
|
-
if params[:version].to_s.gsub(".", "") =~ /\W/ ||
|
84
|
-
params[:version].to_s =~ /\.\./
|
101
|
+
# some params can contain dot, but only one in row
|
102
|
+
if [:resource, :method, :format, :version].any? { |p| params[p].to_s.gsub(".", "") =~ /\W/ || params[p].to_s =~ /\.\./ }
|
85
103
|
head :bad_request and return
|
86
104
|
end
|
87
105
|
|
@@ -7,5 +7,7 @@
|
|
7
7
|
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
8
8
|
})();
|
9
9
|
</script>
|
10
|
-
<noscript
|
11
|
-
|
10
|
+
<noscript><%= t('apipie.enable_javascript_html', :comments_href => link_to(
|
11
|
+
t('apipie.comments_powered_by_disqus', :disqus => 'Disqus'),
|
12
|
+
"http://disqus.com/?ref_noscript")) %></noscript>
|
13
|
+
<a href="http://disqus.com" class="dsq-brlink"><%= t('apipie.comments_powered_by_disqus', :disqus => "<span class="logo-disqus">Disqus</span>") %></a>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<%= raw method[:full_description] %>
|
2
2
|
|
3
3
|
<% unless method[:formats].blank? %>
|
4
|
-
<%= heading('
|
4
|
+
<%= heading(t('apipie.supported_formats'), h_level) %>
|
5
5
|
<%= method[:formats].join(', ') %>
|
6
6
|
<% end %>
|
7
7
|
|
8
8
|
<% unless method[:errors].blank? %>
|
9
|
-
<%= heading('
|
9
|
+
<%= heading(t('apipie.errors'), h_level) %>
|
10
10
|
<% method[:errors].each do |err| %>
|
11
11
|
<%= err[:code] %>
|
12
12
|
<%= err[:description] %>
|
@@ -19,24 +19,24 @@
|
|
19
19
|
<% end %>
|
20
20
|
|
21
21
|
<% unless method[:metadata].blank? %>
|
22
|
-
<%= heading('
|
22
|
+
<%= heading(t('apipie.metadata'), h_level) %>
|
23
23
|
<%= render(:partial => "metadata", :locals => {:meta => method[:metadata]}) %>
|
24
24
|
<% end %>
|
25
25
|
|
26
26
|
<% unless method[:examples].blank? %>
|
27
|
-
<%= heading('
|
27
|
+
<%= heading(t('apipie.examples'), h_level) %>
|
28
28
|
<% method[:examples].each do |example| %>
|
29
29
|
<pre class="prettyprint"><%= example %></pre>
|
30
30
|
<% end %>
|
31
31
|
<% end %>
|
32
32
|
|
33
33
|
<% unless method[:params].blank? %>
|
34
|
-
<%= heading('
|
34
|
+
<%= heading(t('apipie.params'), h_level) %>
|
35
35
|
<table class='table'>
|
36
36
|
<thead>
|
37
37
|
<tr>
|
38
|
-
<th
|
39
|
-
<th
|
38
|
+
<th><%= t('aapipie.param_name') %></th>
|
39
|
+
<th><%= t('apipie.description') %></th>
|
40
40
|
</tr>
|
41
41
|
</thead>
|
42
42
|
<tbody>
|
@@ -9,8 +9,8 @@
|
|
9
9
|
<td>
|
10
10
|
<strong><%= param[:full_name] %> </strong><br>
|
11
11
|
<small>
|
12
|
-
<%= param[:required] ? 'required' : 'optional' %>
|
13
|
-
<%= param[:allow_nil] ? ',
|
12
|
+
<%= param[:required] ? t('apipie.required') : t('apipie.optional') %>
|
13
|
+
<%= param[:allow_nil] ? ', '+t('apipie.nil_allowed') : '' %>
|
14
14
|
</small>
|
15
15
|
</td>
|
16
16
|
<td>
|
@@ -7,8 +7,8 @@
|
|
7
7
|
<li>
|
8
8
|
<strong><%= param[:name] %> </strong>:
|
9
9
|
<small>
|
10
|
-
<%= param[:required] ? 'required' : 'optional' %>
|
11
|
-
<%= param[:allow_nil] ? ',
|
10
|
+
<%= param[:required] ? t('apipie.required') : t('apipie.optional') %>
|
11
|
+
<%= param[:allow_nil] ? ', '+t('apipie.nil_allowed') : '' %>
|
12
12
|
<% if param[:validator] %>
|
13
13
|
[ <%= param[:validator] %> ]
|
14
14
|
<% end %>
|
@@ -1,14 +1,17 @@
|
|
1
1
|
<h1 class='page-header'>
|
2
|
-
|
2
|
+
<%= t('apipie.oops') %>
|
3
3
|
<small>
|
4
4
|
<% if @resource == 'null' %>
|
5
|
-
|
5
|
+
<%= t('apipie.resource_not_found_html', :resource => "<code>#{params[:resource]}</code>") %>
|
6
6
|
<% else %>
|
7
|
-
|
7
|
+
<%= t('apipie.method_not_found_html', :resource => "<code>#{params[:resource]}</code>",
|
8
|
+
:method => "<code>#{params[:resource]}</code>" %>
|
8
9
|
<% end %>
|
9
10
|
</small>
|
10
11
|
</h1>
|
11
12
|
|
12
13
|
<% if @doc %>
|
13
|
-
|
14
|
+
<%= t('apipie.goto_homepage_html', :href = link_to(
|
15
|
+
t('apipie.goto_homepage_href', :app_name => @doc[:name]),
|
16
|
+
File.join(@doc[:doc_url], @doc[:link_extension]))) %>
|
14
17
|
<% end %>
|
@@ -1,4 +1,6 @@
|
|
1
|
-
<h1 class='page-header'
|
2
|
-
<p
|
3
|
-
<p
|
1
|
+
<h1 class='page-header'><%= t('apipie.no_doc_found') %></h1>
|
2
|
+
<p><%= t('apipie.no_docs_found_descr') %></p>
|
3
|
+
<p><%= t('apipie.follow_instructions_html',
|
4
|
+
:href => link_to(t('apipie.follow_instructions_href'),
|
5
|
+
"https://github.com/Pajk/apipie-rails#getting-started", :target => "_blank")) %></p>
|
4
6
|
|
@@ -1,15 +1,16 @@
|
|
1
1
|
<ul class='breadcrumb'>
|
2
2
|
<li class='active'><a href='<%= @doc[:doc_url] %><%= @doc[:link_extension] %>'><%= @doc[:name] %> <%= @doc[:resources].values.first[:version] %></a></li>
|
3
|
+
<%= render(:partial => "languages", :locals => {:doc_url => @doc[:doc_url]}) %>
|
3
4
|
<% if @versions && @versions.size > 1 %>
|
4
5
|
<li class='pull-right'>
|
5
|
-
<%= @versions.collect { |v| link_to v, Apipie.full_url(v) }.join(' / ').html_safe %>
|
6
|
+
<%= @versions.collect { |v| link_to v, Apipie.full_url(v+@doc[:link_extension]) }.join(' / ').html_safe %>
|
6
7
|
</li>
|
7
8
|
<% end %>
|
8
9
|
</ul>
|
9
10
|
|
10
11
|
<div><%= raw @doc[:info] %></div>
|
11
12
|
|
12
|
-
<h1 class='page-header'
|
13
|
+
<h1 class='page-header'><%= t('apipie.resources') %></h1>
|
13
14
|
|
14
15
|
<% @doc[:resources].sort_by(&:first).each do |key, api| %>
|
15
16
|
<h2>
|
@@ -21,8 +22,8 @@
|
|
21
22
|
<table class='table'>
|
22
23
|
<thead>
|
23
24
|
<tr>
|
24
|
-
<th
|
25
|
-
<th
|
25
|
+
<th><%= t('apipie.resource') %></th>
|
26
|
+
<th><%= t('apipie.description') %></th>
|
26
27
|
</tr>
|
27
28
|
</thead>
|
28
29
|
<tbody>
|
@@ -38,6 +39,6 @@
|
|
38
39
|
</table>
|
39
40
|
<% end %>
|
40
41
|
|
41
|
-
<% content_for
|
42
|
-
<%= raw
|
42
|
+
<% unless content_for(:apipie_footer) == @doc[:copyright] %>
|
43
|
+
<%= content_for :apipie_footer, raw(@doc[:copyright]) %>
|
43
44
|
<% end %>
|
@@ -11,6 +11,8 @@
|
|
11
11
|
<span class='divider'>/</span>
|
12
12
|
</li>
|
13
13
|
<li class='active'><%= @method[:name] %></li>
|
14
|
+
<%= render(:partial => "languages", :locals => {:doc_url => @method[:doc_url]}) %>
|
15
|
+
|
14
16
|
</ul>
|
15
17
|
|
16
18
|
<% @method[:apis].each do |api| %>
|
@@ -30,6 +32,6 @@
|
|
30
32
|
<%= render(:partial => "method_detail", :locals => {:method => @method, :h_level => 2}) %>
|
31
33
|
</div>
|
32
34
|
|
33
|
-
<% content_for
|
34
|
-
<%= raw
|
35
|
+
<% unless content_for(:apipie_footer) == @doc[:copyright] %>
|
36
|
+
<%= content_for :apipie_footer, raw(@doc[:copyright]) %>
|
35
37
|
<% end %>
|
@@ -45,14 +45,14 @@
|
|
45
45
|
<div>
|
46
46
|
<%= raw method[:full_description] %>
|
47
47
|
<% unless method[:examples].blank? %>
|
48
|
-
<h4
|
48
|
+
<h4><%= t('apipie.examples') %></h4>
|
49
49
|
<% method[:examples].each do |example| %>
|
50
50
|
<pre class="wiki"><%= example %></pre>
|
51
51
|
<% end %>
|
52
52
|
<% end %>
|
53
53
|
|
54
54
|
<% unless method[:errors].blank? %>
|
55
|
-
<h4
|
55
|
+
<h4><%= t('apipie.errors') %></h4>
|
56
56
|
<% method[:errors].each do |err| %>
|
57
57
|
<%= err[:code] %>
|
58
58
|
<%= err[:description] %>
|
@@ -62,7 +62,7 @@
|
|
62
62
|
<% end %>
|
63
63
|
|
64
64
|
<% unless method[:params].blank? %>
|
65
|
-
<h4
|
65
|
+
<h4><%= t('apipie.params') %></h4>
|
66
66
|
<%= render(:partial => "params_plain", :locals => {:params => method[:params]}) %>
|
67
67
|
<% end %>
|
68
68
|
</div>
|