apipie-rails 0.0.24 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -1,29 +1,31 @@
|
|
1
1
|
module Api
|
2
2
|
module V2
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module Nested
|
4
|
+
class ArchitecturesController < V2::BaseController
|
5
|
+
resource_description { name 'Architectures' }
|
6
|
+
api :GET, "/nested/architectures/", "List all nested architectures."
|
7
|
+
def index
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
api :GET, "/nested/architectures/:id/", "Show a nested architecture."
|
11
|
+
def show
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
api :POST, "/nested/architectures/", "Create a nested architecture."
|
15
|
+
param_group :arch, Api::V1::ArchitecturesController
|
16
|
+
def create
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
api :PUT, "/nested/architectures/:id/", "Update a nested architecture."
|
20
|
+
param :architecture, Hash, :required => true do
|
21
|
+
param :name, String
|
22
|
+
end
|
23
|
+
def update
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
26
|
+
api :DELETE, "/architecturess/:id/", "Delete a nested architecture."
|
27
|
+
def destroy
|
28
|
+
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -1,39 +1,41 @@
|
|
1
|
-
module Concerns
|
2
|
-
|
1
|
+
module Concerns
|
2
|
+
module SampleController
|
3
|
+
extend Apipie::DSL::Concern
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
api :GET, '/:controller_path'
|
6
|
+
def index
|
7
|
+
render :text => "OK #{params.inspect}"
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
api :GET, '/:resource_id/:id'
|
11
|
+
param :id, String
|
12
|
+
def show
|
13
|
+
render :text => "OK #{params.inspect}"
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def_param_group :concern do
|
17
|
+
param :concern, Hash, :required => true, :action_aware => true do
|
18
|
+
param :name, String, "Name of a :concern"
|
19
|
+
param :concern_type, String
|
20
|
+
end
|
19
21
|
end
|
20
|
-
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
api :POST, '/:resource_id', "Create a :concern"
|
24
|
+
param_group :concern
|
25
|
+
def create
|
26
|
+
render :text => "OK #{params.inspect}"
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
29
|
+
api :PUT, '/:resource_id/:id'
|
30
|
+
param :id, String
|
31
|
+
param_group :concern
|
32
|
+
def update
|
33
|
+
render :text => "OK #{params.inspect}"
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
api :GET, '/:resource_id/:custom_subst'
|
37
|
+
def custom
|
38
|
+
render :text => "OK #{params.inspect}"
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
@@ -5,13 +5,16 @@ class UsersController < ApplicationController
|
|
5
5
|
path '/users'
|
6
6
|
formats ['json']
|
7
7
|
param :id, Fixnum, :desc => "User ID", :required => false
|
8
|
-
param :
|
9
|
-
param :
|
10
|
-
|
8
|
+
param :legacy_param, Hash, :desc => 'Deprecated parameter not documented', :show => false, :required => false do
|
9
|
+
param :resource_param, Hash, :desc => 'Param description for all methods' do
|
10
|
+
param :ausername, String, :desc => "Username for login", :required => true
|
11
|
+
param :apassword, String, :desc => "Password for login", :required => true
|
12
|
+
end
|
11
13
|
end
|
12
14
|
api_version "development"
|
13
|
-
error 404, "Missing"
|
15
|
+
error 404, "Missing", :meta => {:some => "metadata"}
|
14
16
|
error 500, "Server crashed for some <%= reason %>"
|
17
|
+
meta :new_style => true, :author => { :name => 'John', :surname => 'Doe' }
|
15
18
|
description <<-EOS
|
16
19
|
== Long description
|
17
20
|
|
@@ -177,6 +180,13 @@ class UsersController < ApplicationController
|
|
177
180
|
val == "param value" ? true : "The only good value is 'param value'."
|
178
181
|
}, :desc => "proc validator"
|
179
182
|
param :briefer_dsl, String, "You dont need :desc => from now"
|
183
|
+
param :meta_param, String, :desc => "A parameter with some additional metadata", :meta => [:some, :more, :info]
|
184
|
+
meta :success_message => "Some message"
|
185
|
+
param :hash_param, Hash, :desc => "Hash param" do
|
186
|
+
param :dummy_hash, Hash do
|
187
|
+
param :dummy_2, String, :required => true
|
188
|
+
end
|
189
|
+
end
|
180
190
|
def show
|
181
191
|
unless params[:session] == "secret_hash"
|
182
192
|
render :text => "Not authorized", :status => 401
|
@@ -212,8 +222,11 @@ class UsersController < ApplicationController
|
|
212
222
|
render :text => "OK #{params.inspect}"
|
213
223
|
end
|
214
224
|
|
215
|
-
api :PUT, "/users/:id", "
|
225
|
+
api :PUT, "/users/:id", "Update an user"
|
216
226
|
param_group :user
|
227
|
+
param :comments, Array do
|
228
|
+
param :comment, String
|
229
|
+
end
|
217
230
|
def update
|
218
231
|
render :text => "OK #{params.inspect}"
|
219
232
|
end
|
@@ -4,6 +4,28 @@ describe Apipie::MethodDescription do
|
|
4
4
|
|
5
5
|
let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
|
6
6
|
|
7
|
+
describe "metadata" do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@resource = Apipie::ResourceDescription.new(ApplicationController, "dummy")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return nil when no metadata is provided" do
|
14
|
+
method = Apipie::MethodDescription.new(:a, @resource, dsl_data)
|
15
|
+
method.to_json[:metadata].should == nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return the metadata" do
|
19
|
+
meta = {
|
20
|
+
:lenght => 32,
|
21
|
+
:weight => '830g'
|
22
|
+
}
|
23
|
+
method = Apipie::MethodDescription.new(:a, @resource, dsl_data.update(:meta => meta))
|
24
|
+
method.to_json[:metadata].should == meta
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
7
29
|
describe "params descriptions" do
|
8
30
|
|
9
31
|
before(:each) do
|
@@ -12,6 +12,73 @@ describe Apipie::ParamDescription do
|
|
12
12
|
Apipie::MethodDescription.new(:show, resource_desc, dsl_data)
|
13
13
|
end
|
14
14
|
|
15
|
+
describe "metadata" do
|
16
|
+
|
17
|
+
it "should return nil when no metadata is provided" do
|
18
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String)
|
19
|
+
param.to_json[:metadata].should == nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return the metadata" do
|
23
|
+
meta = {
|
24
|
+
:lenght => 32,
|
25
|
+
:weight => '830g'
|
26
|
+
}
|
27
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String, :meta => meta)
|
28
|
+
param.to_json[:metadata].should == meta
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "show option" do
|
34
|
+
|
35
|
+
it "should return true when show option is not provided" do
|
36
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String)
|
37
|
+
param.to_json[:show].should == true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return the show option" do
|
41
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String, :show => true)
|
42
|
+
param.to_json[:show].should == true
|
43
|
+
|
44
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String, :show => false)
|
45
|
+
param.to_json[:show].should == false
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "full_name" do
|
51
|
+
context "with no nested parameters" do
|
52
|
+
|
53
|
+
it "should return name" do
|
54
|
+
param = Apipie::ParamDescription.new(method_desc, :some_param, String)
|
55
|
+
param.to_json[:full_name].should == 'some_param'
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with nested parameters" do
|
61
|
+
|
62
|
+
it "should return the parameter's name nested in the parents name" do
|
63
|
+
parent_param = Apipie::ParamDescription.new(method_desc, :parent, String)
|
64
|
+
nested_param = Apipie::ParamDescription.new(method_desc, :nested, String, :parent => parent_param)
|
65
|
+
|
66
|
+
nested_param.to_json[:full_name].should == 'parent[nested]'
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with the parent parameter set to not show" do
|
70
|
+
|
71
|
+
it "should return just the parameter's name" do
|
72
|
+
parent_param = Apipie::ParamDescription.new(method_desc, :parent, String, :show => false)
|
73
|
+
nested_param = Apipie::ParamDescription.new(method_desc, :nested, String, :parent => parent_param)
|
74
|
+
|
75
|
+
nested_param.to_json[:full_name].should == 'nested'
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
15
82
|
describe "validator selection" do
|
16
83
|
|
17
84
|
it "should allow nil validator" do
|
@@ -171,4 +238,14 @@ describe Apipie::ParamDescription do
|
|
171
238
|
end
|
172
239
|
end
|
173
240
|
end
|
241
|
+
|
242
|
+
|
243
|
+
describe "Array with classes" do
|
244
|
+
it "should be valid for objects included in class array" do
|
245
|
+
param = Apipie::ParamDescription.new(method_desc, :param, [Fixnum, String])
|
246
|
+
expect { param.validate("1") }.should_not raise_error
|
247
|
+
expect { param.validate(Fixnum) }.should raise_error
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
174
251
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'rake tasks' do
|
4
|
+
include_context "rake"
|
5
|
+
|
6
|
+
before do
|
7
|
+
Apipie.stub(:reload_documentation)
|
8
|
+
subject.invoke(*task_args)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'static pages' do
|
12
|
+
|
13
|
+
let(:apidoc_html) do
|
14
|
+
File.read("#{doc_output}.html")
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:doc_output) do
|
18
|
+
File.join(::Rails.root, 'doc', 'apidoc')
|
19
|
+
end
|
20
|
+
|
21
|
+
after do
|
22
|
+
Dir["#{doc_output}*"].each { |static_file| FileUtils.rm_rf(static_file) }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'apipie:static' do
|
26
|
+
it "generates static files for the default version of apipie docs" do
|
27
|
+
apidoc_html.should =~ /Test app #{Apipie.configuration.default_version}/
|
28
|
+
end
|
29
|
+
|
30
|
+
it "includes the stylesheets" do
|
31
|
+
apidoc_html.should include('./apidoc/stylesheets/bundled/bootstrap.min.css')
|
32
|
+
File.should exist(File.join(doc_output, 'stylesheets/bundled/bootstrap.min.css'))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'apipie:static[2.0]' do
|
37
|
+
it "generates static files for the default version of apipie docs" do
|
38
|
+
apidoc_html.should =~ /Test app 2.0/
|
39
|
+
end
|
40
|
+
|
41
|
+
it "includes the stylesheets" do
|
42
|
+
apidoc_html.should include('./apidoc/stylesheets/bundled/bootstrap.min.css')
|
43
|
+
File.should exist(File.join(doc_output, 'stylesheets/bundled/bootstrap.min.css'))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'apipie:cache' do
|
49
|
+
let(:cache_output) do
|
50
|
+
File.join(::Rails.root, 'public', 'apipie-cache')
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:apidoc_html) do
|
54
|
+
File.read("#{cache_output}.html")
|
55
|
+
end
|
56
|
+
|
57
|
+
after do
|
58
|
+
Dir["#{cache_output}*"].each { |static_file| FileUtils.rm_rf(static_file) }
|
59
|
+
end
|
60
|
+
|
61
|
+
it "generates cache files" do
|
62
|
+
File.should exist(File.join(cache_output, 'apidoc.html'))
|
63
|
+
File.should exist(File.join(cache_output, 'apidoc/development.html'))
|
64
|
+
File.should exist(File.join(cache_output, 'apidoc/development/users.html'))
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -4,6 +4,24 @@ describe Apipie::ResourceDescription do
|
|
4
4
|
|
5
5
|
let(:dsl_data) { ActionController::Base.send(:_apipie_dsl_data_init) }
|
6
6
|
|
7
|
+
describe "metadata" do
|
8
|
+
|
9
|
+
it "should return nil when no metadata is provided" do
|
10
|
+
resource = Apipie::ResourceDescription.new(ApplicationController, "dummy", dsl_data)
|
11
|
+
resource.to_json[:metadata].should == nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return the metadata" do
|
15
|
+
meta = {
|
16
|
+
:lenght => 32,
|
17
|
+
:weight => '830g'
|
18
|
+
}
|
19
|
+
resource = Apipie::ResourceDescription.new(ApplicationController, "dummy", dsl_data.update(:meta => meta))
|
20
|
+
resource.to_json[:metadata].should == meta
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
7
25
|
describe "methods descriptions" do
|
8
26
|
|
9
27
|
before(:each) do
|
data/spec/lib/validator_spec.rb
CHANGED
@@ -43,4 +43,13 @@ describe Apipie::Validator do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
end
|
46
|
+
|
47
|
+
describe 'ArrayClassValidator' do
|
48
|
+
it "should validate by object class" do
|
49
|
+
validator = Apipie::Validator::ArrayClassValidator.new(params_desc, [Fixnum, String])
|
50
|
+
validator.validate("1").should be_true
|
51
|
+
validator.validate(1).should be_true
|
52
|
+
validator.validate({ 1 => 1 }).should be_false
|
53
|
+
end
|
54
|
+
end
|
46
55
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'bundler/setup'
|
3
3
|
|
4
4
|
ENV["RAILS_ENV"] ||= 'test'
|
5
|
+
APIPIE_ROOT = File.expand_path('../..', __FILE__)
|
5
6
|
require File.expand_path("../dummy/config/environment", __FILE__)
|
6
7
|
|
7
8
|
require 'rspec/rails'
|
@@ -11,7 +12,7 @@ require 'apipie-rails'
|
|
11
12
|
|
12
13
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
13
14
|
# in spec/support/ and its subdirectories.
|
14
|
-
Dir[
|
15
|
+
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f}
|
15
16
|
|
16
17
|
RSpec.configure do |config|
|
17
18
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "rake"
|
2
|
+
|
3
|
+
# inspired by http://robots.thoughtbot.com/test-rake-tasks-like-a-boss
|
4
|
+
shared_context "rake" do
|
5
|
+
let(:rake) { Rake::Application.new }
|
6
|
+
let(:task_name) { rake.parse_task_string(self.class.description).first }
|
7
|
+
let(:task_args) { rake.parse_task_string(self.class.description).last }
|
8
|
+
let(:task_path) { "lib/tasks/apipie" }
|
9
|
+
subject { rake[task_name] }
|
10
|
+
|
11
|
+
def loaded_files_excluding_current_rake_file
|
12
|
+
$".reject {|file| file == File.expand_path("#{task_path}.rake", APIPIE_ROOT) }
|
13
|
+
end
|
14
|
+
|
15
|
+
before do
|
16
|
+
Rake.application = rake
|
17
|
+
Rake.application.rake_require(task_path, [APIPIE_ROOT], loaded_files_excluding_current_rake_file)
|
18
|
+
|
19
|
+
Rake::Task.define_task(:environment)
|
20
|
+
end
|
21
|
+
end
|