apipie-rails 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -1
- data/Gemfile.lock +1 -1
- data/README.rdoc +5 -1
- data/app/views/apipie/apipies/method.html.erb +7 -2
- data/app/views/apipie/apipies/plain.html.erb +2 -2
- data/app/views/apipie/apipies/resource.html.erb +13 -4
- data/app/views/apipie/apipies/static.html.erb +2 -2
- data/lib/apipie/application.rb +8 -1
- data/lib/apipie/client/generator.rb +7 -2
- data/lib/apipie/client/template/base.rb.tt +5 -2
- data/lib/apipie/client/template/client.gemspec.tt +1 -1
- data/lib/apipie/dsl_definition.rb +8 -0
- data/lib/apipie/error_description.rb +5 -1
- data/lib/apipie/method_description.rb +21 -2
- data/lib/apipie/resource_description.rb +13 -1
- data/lib/apipie/version.rb +1 -1
- data/rubygem-apipie-rails.spec +12 -2
- data/spec/controllers/users_controller_spec.rb +24 -13
- data/spec/dummy/app/controllers/users_controller.rb +4 -0
- data/spec/dummy/db/.gitkeep +0 -0
- metadata +5 -2
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm use 1.8.7@apipie
|
1
|
+
rvm use 1.8.7@apipie --create
|
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -108,6 +108,7 @@ be checked in every request.
|
|
108
108
|
[short] One line short description.
|
109
109
|
[path] Relative URL path of this resource.
|
110
110
|
[version] Version of this resource API, use arbitrary string.
|
111
|
+
[formats] Resource level request / response formats.
|
111
112
|
[param] The very same parameter description as you will use method
|
112
113
|
description. Generally use this for parameters that apply
|
113
114
|
to every method in the controller (such as :user hash).
|
@@ -125,6 +126,7 @@ Example:
|
|
125
126
|
short 'Site members'
|
126
127
|
path '/users'
|
127
128
|
version '1.0 - 3.4.2012'
|
129
|
+
formats ['json', 'xml']
|
128
130
|
param :id, Fixnum, :desc => "User ID", :required => false
|
129
131
|
param :user, Hash, :desc => 'Param description for all methods' do
|
130
132
|
param :username, String, :required => true,
|
@@ -151,6 +153,7 @@ Then describe methods available to your API.
|
|
151
153
|
You can use this +api+ method more than once for one method. It could
|
152
154
|
be useful when there are more routes mapped to it.
|
153
155
|
[param] Look at Parameter description section for details.
|
156
|
+
[formats] Method level request / response formats.
|
154
157
|
[error] Describe each possible error that can happend what calling this
|
155
158
|
method. HTTP response code and description can be provided.
|
156
159
|
[description] Full method description which will be converted to HTML by
|
@@ -173,6 +176,7 @@ Example:
|
|
173
176
|
val == "param value" ? true : "The only good value is 'param value'."
|
174
177
|
}, :desc => "proc validator"
|
175
178
|
description "method description"
|
179
|
+
formats ['json', 'jsonp', 'xml']
|
176
180
|
example " 'user': {...} "
|
177
181
|
see "users#showme"
|
178
182
|
def show
|
@@ -300,7 +304,7 @@ So we create apipie_validators.rb initializer with this content:
|
|
300
304
|
|
301
305
|
def validate(value)
|
302
306
|
return false if value.nil?
|
303
|
-
!!(value.to_s =~
|
307
|
+
!!(value.to_s =~ /^[-+]?[0-9]+$/)
|
304
308
|
end
|
305
309
|
|
306
310
|
def self.build(param_description, argument, options, block)
|
@@ -33,11 +33,16 @@
|
|
33
33
|
<% end %>
|
34
34
|
<% end %>
|
35
35
|
|
36
|
+
<% unless @method[:formats].blank? %>
|
37
|
+
<h2>Supported Formats</h2>
|
38
|
+
<%= @method[:formats].join(', ') %>
|
39
|
+
<% end %>
|
40
|
+
|
36
41
|
<% unless @method[:errors].blank? %>
|
37
42
|
<h2>Errors</h2>
|
38
43
|
<% @method[:errors].each do |err| %>
|
39
|
-
<%= err
|
40
|
-
<%= err
|
44
|
+
<%= err[:code] %>
|
45
|
+
<%= err[:description] %>
|
41
46
|
<br>
|
42
47
|
<% end %>
|
43
48
|
<% end %>
|
@@ -10,11 +10,15 @@
|
|
10
10
|
</h1>
|
11
11
|
</div>
|
12
12
|
|
13
|
-
|
14
13
|
<% unless @resource[:full_description].blank? %>
|
15
14
|
<div><%= raw @resource[:full_description] %></div>
|
16
15
|
<% end %>
|
17
16
|
|
17
|
+
<% unless @resource[:formats].blank? %>
|
18
|
+
<h2>Supported Formats</h2>
|
19
|
+
<%= @resource[:formats].join(', ') %>
|
20
|
+
<% end %>
|
21
|
+
|
18
22
|
<div class='accordion' id='accordion'>
|
19
23
|
|
20
24
|
<% @resource[:methods].each do |m| %>
|
@@ -41,13 +45,18 @@
|
|
41
45
|
<% end %>
|
42
46
|
|
43
47
|
<div id='description-<%= m[:name] %>' class='collapse accordion-body'>
|
44
|
-
|
45
48
|
<%= raw m[:full_description] %>
|
49
|
+
|
50
|
+
<% unless m[:formats].blank? %>
|
51
|
+
<h3>Supported Formats</h3>
|
52
|
+
<%= m[:formats].join(', ') %>
|
53
|
+
<% end %>
|
54
|
+
|
46
55
|
<% unless m[:errors].blank? %>
|
47
56
|
<h3>Errors</h3>
|
48
57
|
<% m[:errors].each do |err| %>
|
49
|
-
<%= err
|
50
|
-
<%= err
|
58
|
+
<%= err[:code] %>
|
59
|
+
<%= err[:description] %>
|
51
60
|
<br>
|
52
61
|
<% end %>
|
53
62
|
<% end %>
|
data/lib/apipie/application.rb
CHANGED
@@ -12,7 +12,7 @@ module Apipie
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
attr_accessor :last_api_args, :last_errors, :last_params, :last_description, :last_examples, :last_see
|
15
|
+
attr_accessor :last_api_args, :last_errors, :last_params, :last_description, :last_examples, :last_see, :last_formats
|
16
16
|
attr_reader :method_descriptions, :resource_descriptions
|
17
17
|
|
18
18
|
def initialize
|
@@ -109,6 +109,7 @@ module Apipie
|
|
109
109
|
@last_description = nil
|
110
110
|
@last_examples = []
|
111
111
|
@last_see = nil
|
112
|
+
@last_formats = []
|
112
113
|
end
|
113
114
|
|
114
115
|
# Return the current description, clearing it in the process.
|
@@ -136,6 +137,12 @@ module Apipie
|
|
136
137
|
see
|
137
138
|
end
|
138
139
|
|
140
|
+
def get_formats
|
141
|
+
formats = @last_formats
|
142
|
+
@last_formats = nil
|
143
|
+
formats
|
144
|
+
end
|
145
|
+
|
139
146
|
def get_params
|
140
147
|
params = @last_params.clone
|
141
148
|
@last_params.clear
|
@@ -68,12 +68,17 @@ module Apipie
|
|
68
68
|
|
69
69
|
protected
|
70
70
|
|
71
|
+
def camelizer(string)
|
72
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
73
|
+
string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$2.capitalize}" }
|
74
|
+
end
|
75
|
+
|
71
76
|
def class_base
|
72
|
-
@class_base ||= name
|
77
|
+
@class_base ||= camelizer(name)
|
73
78
|
end
|
74
79
|
|
75
80
|
def class_suffix
|
76
|
-
@class_suffix ||= suffix
|
81
|
+
@class_suffix ||= camelizer(suffix)
|
77
82
|
end
|
78
83
|
|
79
84
|
def plaintext(text)
|
@@ -17,8 +17,11 @@ module <%= class_base %><%= class_suffix %>
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def call(method, path, payload = nil)
|
20
|
-
|
21
|
-
|
20
|
+
if payload && (method == :post || method == :put)
|
21
|
+
# TODO: is this neccessary? RestClient converts it automaticaly for me.
|
22
|
+
payload = payload.to_json
|
23
|
+
end
|
24
|
+
ret = client[path].send(*([method, payload].compact))
|
22
25
|
data = begin
|
23
26
|
JSON.parse(ret.body)
|
24
27
|
rescue JSON::ParserError
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = <%= class_base %><%= class_suffix %>::VERSION
|
17
17
|
|
18
|
-
gem.add_dependency 'thor', '>= 0.15.4'
|
18
|
+
<% if all? %>gem.add_dependency 'thor', '>= 0.15.4'<% end %>
|
19
19
|
gem.add_dependency 'json'
|
20
20
|
gem.add_dependency 'rest-client', '>= 1.6.1'
|
21
21
|
gem.add_dependency 'oauth'
|
@@ -66,6 +66,14 @@ module Apipie
|
|
66
66
|
Apipie.add_example(example)
|
67
67
|
end
|
68
68
|
|
69
|
+
# Describe available request/response formats
|
70
|
+
#
|
71
|
+
# formats ['json', 'jsonp', 'xml']
|
72
|
+
def formats(formats) #:doc:
|
73
|
+
return unless Apipie.active_dsl?
|
74
|
+
Apipie.last_formats = formats
|
75
|
+
end
|
76
|
+
|
69
77
|
# Describe possible errors
|
70
78
|
#
|
71
79
|
# Example:
|
@@ -23,7 +23,7 @@ module Apipie
|
|
23
23
|
|
24
24
|
end
|
25
25
|
|
26
|
-
attr_reader :
|
26
|
+
attr_reader :full_description, :method, :resource, :apis, :examples, :see, :formats
|
27
27
|
|
28
28
|
def initialize(method, resource, app)
|
29
29
|
@method = method
|
@@ -31,6 +31,7 @@ module Apipie
|
|
31
31
|
|
32
32
|
@apis = app.get_api_args
|
33
33
|
@see = app.get_see
|
34
|
+
@formats = app.get_formats
|
34
35
|
|
35
36
|
desc = app.get_description || ''
|
36
37
|
@full_description = Apipie.markup_to_html(desc)
|
@@ -72,6 +73,19 @@ module Apipie
|
|
72
73
|
all_params.find_all(&:validator)
|
73
74
|
end
|
74
75
|
|
76
|
+
def errors
|
77
|
+
return @merged_errors if @merged_errors
|
78
|
+
@merged_errors = []
|
79
|
+
if @resource
|
80
|
+
# exclude overwritten parent errors
|
81
|
+
@merged_errors = @resource._errors_ordered.find_all do |err|
|
82
|
+
!@errors.any? { |e| e.code == err.code }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
@merged_errors.concat(@errors)
|
86
|
+
return @merged_errors
|
87
|
+
end
|
88
|
+
|
75
89
|
def doc_url
|
76
90
|
Apipie.full_url("#{@resource._id}/#{@method}")
|
77
91
|
end
|
@@ -100,13 +114,18 @@ module Apipie
|
|
100
114
|
@see
|
101
115
|
end
|
102
116
|
|
117
|
+
def formats
|
118
|
+
@formats || @resource._formats
|
119
|
+
end
|
120
|
+
|
103
121
|
def to_json
|
104
122
|
{
|
105
123
|
:doc_url => doc_url,
|
106
124
|
:name => @method,
|
107
125
|
:apis => method_apis_to_json,
|
126
|
+
:formats => formats,
|
108
127
|
:full_description => @full_description,
|
109
|
-
:errors =>
|
128
|
+
:errors => errors.map(&:to_json),
|
110
129
|
:params => params_ordered.map(&:to_json).flatten,
|
111
130
|
:examples => @examples,
|
112
131
|
:see => @see,
|
@@ -8,14 +8,16 @@ module Apipie
|
|
8
8
|
# methods - array of keys to Apipie.method_descriptions (array of Apipie::MethodDescription)
|
9
9
|
# name - human readable alias of resource (Articles)
|
10
10
|
# id - resouce name
|
11
|
+
# formats - acceptable request/response format types
|
11
12
|
class ResourceDescription
|
12
13
|
|
13
14
|
attr_reader :controller, :_short_description, :_full_description, :_methods, :_id,
|
14
|
-
:_path, :_version, :_name, :_params_ordered
|
15
|
+
:_path, :_version, :_name, :_params_ordered, :_errors_ordered, :_formats
|
15
16
|
|
16
17
|
def initialize(controller, resource_name, &block)
|
17
18
|
@_methods = []
|
18
19
|
@_params_ordered = []
|
20
|
+
@_errors_ordered = []
|
19
21
|
|
20
22
|
@controller = controller
|
21
23
|
@_id = resource_name
|
@@ -24,6 +26,7 @@ module Apipie
|
|
24
26
|
@_full_description = ""
|
25
27
|
@_short_description = ""
|
26
28
|
@_path = ""
|
29
|
+
@_formats = []
|
27
30
|
|
28
31
|
block.arity < 1 ? instance_eval(&block) : block.call(self) if block_given?
|
29
32
|
end
|
@@ -33,10 +36,18 @@ module Apipie
|
|
33
36
|
@_params_ordered << param_description
|
34
37
|
end
|
35
38
|
|
39
|
+
def error(*args)
|
40
|
+
error_description = Apipie::ErrorDescription.new(args)
|
41
|
+
@_errors_ordered << error_description
|
42
|
+
end
|
43
|
+
|
44
|
+
|
36
45
|
def path(path); @_path = path; end
|
37
46
|
|
38
47
|
def version(version); @_version = version; end
|
39
48
|
|
49
|
+
def formats(formats); @_formats = formats; end
|
50
|
+
|
40
51
|
def name(name); @_name = name; end
|
41
52
|
|
42
53
|
def short(short); @_short_description = short; end
|
@@ -76,6 +87,7 @@ module Apipie
|
|
76
87
|
:short_description => @_short_description,
|
77
88
|
:full_description => @_full_description,
|
78
89
|
:version => @_version,
|
90
|
+
:formats => @_formats,
|
79
91
|
:methods => _methods
|
80
92
|
}
|
81
93
|
end
|
data/lib/apipie/version.rb
CHANGED
data/rubygem-apipie-rails.spec
CHANGED
@@ -10,14 +10,16 @@
|
|
10
10
|
|
11
11
|
Summary: Rails API documentation tool and client generator.
|
12
12
|
Name: rubygem-%{gemname}
|
13
|
-
Version: 0.0.
|
14
|
-
Release:
|
13
|
+
Version: 0.0.9
|
14
|
+
Release: 0%{?dist}
|
15
15
|
Group: Development/Libraries
|
16
16
|
License: MIT
|
17
17
|
URL: http://github.com/Pajk/apipie-rails
|
18
18
|
Source0: http://rubygems.org/downloads/%{gemname}-%{version}.gem
|
19
19
|
Requires: ruby(abi) >= %{rubyabi}
|
20
|
+
Requires: rubygems
|
20
21
|
BuildRequires: ruby(abi) >= %{rubyabi}
|
22
|
+
BuildRequires: rubygems
|
21
23
|
BuildArch: noarch
|
22
24
|
Provides: rubygem(%{gemname}) = %{version}
|
23
25
|
|
@@ -56,6 +58,7 @@ cp -a .%{gemdir}/* \
|
|
56
58
|
%exclude %{geminstdir}/.rvmrc
|
57
59
|
%exclude %{geminstdir}/.travis.yml
|
58
60
|
%exclude %{geminstdir}/rubygem-apipie-rails.spec
|
61
|
+
%exclude %{geminstdir}/.yardoc
|
59
62
|
%exclude %{gemdir}/cache/%{gemname}-%{version}.gem
|
60
63
|
%exclude %{gemdir}/doc/%{gemname}-%{version}
|
61
64
|
|
@@ -65,6 +68,13 @@ cp -a .%{gemdir}/* \
|
|
65
68
|
%doc %{geminstdir}/NOTICE
|
66
69
|
|
67
70
|
%changelog
|
71
|
+
* Thu Jul 26 2012 Pavel Pokorný <pajkycz@gmail.com> 0.0.8-3
|
72
|
+
- Require rubygems in spec file
|
73
|
+
|
74
|
+
* Thu Jul 26 2012 Pavel Pokorný <pajkycz@gmail.com> 0.0.8-2
|
75
|
+
- New version of apipie-rails gem
|
76
|
+
- Generated client improvements
|
77
|
+
|
68
78
|
* Thu Jul 26 2012 Pavel Pokorný <pajkycz@gmail.com> 0.0.7-2
|
69
79
|
- removed doc files from rpm
|
70
80
|
|
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
def compare_hashes(h1, h2)
|
4
|
-
h1.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
val.
|
9
|
-
compare_hashes val
|
4
|
+
if h1.is_a? String
|
5
|
+
h1.should eq(h2)
|
6
|
+
else
|
7
|
+
h1.each do |key, val|
|
8
|
+
if val.is_a? Hash
|
9
|
+
compare_hashes val, h2[key]
|
10
|
+
elsif val.is_a? Array
|
11
|
+
val.each_with_index do |v, i|
|
12
|
+
compare_hashes val[i], h2[key][i]
|
13
|
+
end
|
14
|
+
else
|
15
|
+
val.should eq(h2[key])
|
10
16
|
end
|
11
|
-
else
|
12
|
-
val.should eq(h2[key])
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -34,6 +38,7 @@ describe UsersController do
|
|
34
38
|
subject._path.should eq('/users')
|
35
39
|
subject._version.should eq('1.0 - 3.4.2012')
|
36
40
|
subject._name.should eq('Members')
|
41
|
+
subject._formats.should eq(['json'])
|
37
42
|
end
|
38
43
|
|
39
44
|
it "should contain params defined on resource level" do
|
@@ -202,6 +207,7 @@ describe UsersController do
|
|
202
207
|
it "should contain basic info about method" do
|
203
208
|
a = Apipie[UsersController, :create]
|
204
209
|
a.apis.count.should == 1
|
210
|
+
a.formats.should eq(['json'])
|
205
211
|
api = a.apis.first
|
206
212
|
api.short_description.should eq("Create user")
|
207
213
|
api.api_url.should eq("/api/users")
|
@@ -213,6 +219,7 @@ describe UsersController do
|
|
213
219
|
b.resource._id.should eq('users')
|
214
220
|
|
215
221
|
b.apis.count.should == 1
|
222
|
+
b.formats.should eq(['json', 'jsonp'])
|
216
223
|
api = b.apis.first
|
217
224
|
api.short_description.should eq("Show user profile")
|
218
225
|
api.api_url.should eq("#{Apipie.configuration.api_base_url}/users/:id")
|
@@ -246,10 +253,12 @@ describe UsersController do
|
|
246
253
|
it "should contain possible errors description" do
|
247
254
|
a = Apipie.get_method_description(UsersController, :show)
|
248
255
|
|
249
|
-
a.errors[0].code.should eq(
|
250
|
-
a.errors[0].description.should
|
251
|
-
a.errors[1].code.should eq(
|
252
|
-
a.errors[1].description.should eq("
|
256
|
+
a.errors[0].code.should eq(500)
|
257
|
+
a.errors[0].description.should include("crashed")
|
258
|
+
a.errors[1].code.should eq(401)
|
259
|
+
a.errors[1].description.should eq("Unauthorized")
|
260
|
+
a.errors[2].code.should eq(404)
|
261
|
+
a.errors[2].description.should eq("Not Found")
|
253
262
|
end
|
254
263
|
|
255
264
|
it "should contain all params description" do
|
@@ -276,9 +285,11 @@ describe UsersController do
|
|
276
285
|
it "should be described by valid json" do
|
277
286
|
json = Apipie[UsersController, :two_urls].to_json
|
278
287
|
expected_hash = {
|
279
|
-
:errors => [
|
288
|
+
:errors => [{:code=>404, :description=>"Missing"},
|
289
|
+
{:code=>500, :description=>"Server crashed for some <%= reason %>"}],
|
280
290
|
:examples => [],
|
281
291
|
:doc_url => "#{Apipie.configuration.doc_base_url}/users/two_urls",
|
292
|
+
:formats=>["json"],
|
282
293
|
:full_description => '',
|
283
294
|
:params => [{:full_name=>"oauth",
|
284
295
|
:required=>false,
|
@@ -5,11 +5,14 @@ class UsersController < ApplicationController
|
|
5
5
|
short 'Site members'
|
6
6
|
path '/users'
|
7
7
|
version '1.0 - 3.4.2012'
|
8
|
+
formats ['json']
|
8
9
|
param :id, Fixnum, :desc => "User ID", :required => false
|
9
10
|
param :resource_param, Hash, :desc => 'Param description for all methods' do
|
10
11
|
param :ausername, String, :desc => "Username for login", :required => true
|
11
12
|
param :apassword, String, :desc => "Password for login", :required => true
|
12
13
|
end
|
14
|
+
error 404, "Missing"
|
15
|
+
error 500, "Server crashed for some <%= reason %>"
|
13
16
|
description <<-EOS
|
14
17
|
== Long description
|
15
18
|
|
@@ -163,6 +166,7 @@ class UsersController < ApplicationController
|
|
163
166
|
More builder documentation can be found at http://builder.rubyforge.org.
|
164
167
|
eos
|
165
168
|
api :GET, "/users/:id", "Show user profile"
|
169
|
+
formats ['json', 'jsonp']
|
166
170
|
error 401, "Unauthorized"
|
167
171
|
error :code => 404, :description => "Not Found"
|
168
172
|
param :id, Integer, :desc => "user id", :required => true
|
File without changes
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apipie-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-07-
|
13
|
+
date: 2012-07-31 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-rails
|
@@ -222,6 +222,7 @@ files:
|
|
222
222
|
- spec/dummy/config/initializers/session_store.rb
|
223
223
|
- spec/dummy/config/locales/en.yml
|
224
224
|
- spec/dummy/config/routes.rb
|
225
|
+
- spec/dummy/db/.gitkeep
|
225
226
|
- spec/dummy/doc/apipie_examples.yml
|
226
227
|
- spec/dummy/public/404.html
|
227
228
|
- spec/dummy/public/422.html
|
@@ -284,6 +285,7 @@ test_files:
|
|
284
285
|
- spec/dummy/config/initializers/session_store.rb
|
285
286
|
- spec/dummy/config/locales/en.yml
|
286
287
|
- spec/dummy/config/routes.rb
|
288
|
+
- spec/dummy/db/.gitkeep
|
287
289
|
- spec/dummy/doc/apipie_examples.yml
|
288
290
|
- spec/dummy/public/404.html
|
289
291
|
- spec/dummy/public/422.html
|
@@ -298,3 +300,4 @@ test_files:
|
|
298
300
|
- spec/dummy/public/stylesheets/.gitkeep
|
299
301
|
- spec/dummy/script/rails
|
300
302
|
- spec/spec_helper.rb
|
303
|
+
has_rdoc:
|