optionsful 0.1.7 → 0.1.8
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/README.textile +4 -4
- data/lib/baurets/optionsful/config.rb +27 -13
- data/lib/baurets/optionsful/documentator.rb +46 -38
- data/lib/baurets/optionsful/server.rb +1 -1
- data/lib/baurets/optionsful/version.rb +1 -1
- data/spec/fixtures/optionsful.yml +11 -0
- data/spec/fixtures/optionsful_bug.yml +0 -0
- data/spec/optionsful_config_spec.rb +44 -0
- data/spec/optionsful_documentator_spec.rb +81 -4
- data/spec/optionsful_server_spec.rb +68 -24
- data/spec/samples/app/controllers/comments_controller.rb +86 -0
- data/spec/samples/app/controllers/notes_controller.rb +6 -0
- data/spec/samples/app/controllers/posts_controller.rb +185 -0
- data/spec/samples/app/controllers/teams_controller.rb +33 -0
- data/spec/samples/app/controllers/trips_controller.rb +82 -0
- data/spec/spec_helper.rb +6 -0
- metadata +23 -15
data/README.textile
CHANGED
@@ -20,7 +20,7 @@ HTTP/1.1 204 No Content
|
|
20
20
|
Allow: GET, POST
|
21
21
|
Connection: close
|
22
22
|
Date: Thu, 22 Jul 2010 17:20:27 GMT
|
23
|
-
Link: <http://localhost:3000/
|
23
|
+
Link: <http://localhost:3000/optionsful/posts>; type=text/html; rel=help
|
24
24
|
|
25
25
|
OPTIONS /posts/1 HTTP/1.1
|
26
26
|
Host: http://localhost:3000
|
@@ -29,7 +29,7 @@ HTTP/1.1 204 No Content
|
|
29
29
|
Allow: GET, PUT, DELETE
|
30
30
|
Connection: close
|
31
31
|
Date: Thu, 22 Jul 2010 18:14:24 GMT
|
32
|
-
Link: <http://localhost:3000/
|
32
|
+
Link: <http://localhost:3000/optionsful/posts/1/>; type=text/html; rel=help
|
33
33
|
|
34
34
|
OPTIONS /posts/1/comments HTTP/1.1
|
35
35
|
Host: http://localhost:3000
|
@@ -38,7 +38,7 @@ HTTP/1.1 204 No Content
|
|
38
38
|
Allow: GET, POST
|
39
39
|
Connection: close
|
40
40
|
Date: Thu, 22 Jul 2010 18:12:43 GMT
|
41
|
-
Link: <http://localhost:3000/
|
41
|
+
Link: <http://localhost:3000/optionsful/posts/1/comments>; type=text/html; rel=help
|
42
42
|
|
43
43
|
</pre>
|
44
44
|
~Note the empty line which is part of the HTTP protocol.~
|
@@ -46,7 +46,7 @@ Link: <http://localhost:3000/opts/posts/1/comments>; type=text/html; rel=help
|
|
46
46
|
h3. Retrieving the resource/service documentation right from your browser:
|
47
47
|
|
48
48
|
* Access the given Link header through your preferable browser. Yeah, via an HTTP GET request.
|
49
|
-
* @http://localhost:3000/
|
49
|
+
* @http://localhost:3000/optionsful/posts/1/comments@ for instance.
|
50
50
|
* Try up adding some RDoc-like comments above your actions definitions on the appropriate controllers.
|
51
51
|
* Refresh the page and your documentation and have fun!
|
52
52
|
* There's a lot of helpful things we can do with this extracted 'on-the-fly' information (metadata).
|
@@ -1,35 +1,49 @@
|
|
1
1
|
module Baurets
|
2
2
|
module Optionsful
|
3
|
-
|
4
3
|
class Config
|
5
4
|
|
6
|
-
def initialize
|
7
|
-
|
8
|
-
@config = { :http => {:base_path => "/optionsful"} }
|
5
|
+
def initialize(options = {})
|
6
|
+
@config = configure_options(options)
|
9
7
|
setup
|
8
|
+
self
|
9
|
+
end
|
10
|
+
|
11
|
+
def base_path
|
12
|
+
@config[:http][:base_path]
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def configure_options(options = {})
|
18
|
+
default_opts = { :http => { :base_path => "/optionsful"}, :file => "", :environment => "development" }
|
19
|
+
conf = {}
|
20
|
+
if defined? RAILS_ROOT
|
21
|
+
conf = default_opts.merge!({:file => (File.join(RAILS_ROOT, 'config', 'optionsful.yml'))})
|
22
|
+
else
|
23
|
+
conf = default_opts.merge!({ :http => { :base_path => "/optionsful"} })
|
24
|
+
end
|
25
|
+
conf = conf.merge!(options) unless options.empty?
|
26
|
+
conf
|
10
27
|
end
|
11
28
|
|
12
29
|
def setup
|
13
30
|
require "yaml"
|
31
|
+
yaml_file = @config[:file]
|
14
32
|
begin
|
15
|
-
yaml_file = File.join(RAILS_ROOT, "config", "optionsful.yml")
|
16
33
|
if File.exist? yaml_file
|
17
|
-
conf = YAML::load_file(yaml_file)[
|
34
|
+
conf = YAML::load_file(yaml_file)[@config[:environment]].symbolize_keys
|
18
35
|
configure(conf) if conf
|
19
36
|
end
|
20
37
|
rescue
|
21
38
|
end
|
22
39
|
end
|
40
|
+
|
23
41
|
def configure(conf)
|
24
|
-
@config[:http][:base_path] = conf[:http][
|
42
|
+
@config[:http][:base_path] = conf[:http]["base_path"] if (conf[:http] && conf[:http]["base_path"])
|
43
|
+
@config[:file] = conf[:file] if conf[:file]
|
44
|
+
@config[:environment] = conf[:environment] if conf[:environment]
|
25
45
|
end
|
26
46
|
|
27
|
-
|
28
|
-
def base_path
|
29
|
-
@config[:http][:base_path]
|
30
|
-
end
|
31
|
-
|
32
47
|
end
|
33
|
-
|
34
48
|
end
|
35
49
|
end
|
@@ -4,19 +4,16 @@ module Baurets
|
|
4
4
|
|
5
5
|
def initialize(app)
|
6
6
|
@app = app
|
7
|
-
@config =
|
7
|
+
@config = Baurets::Optionsful::Config.new
|
8
8
|
end
|
9
9
|
|
10
10
|
def call(env)
|
11
|
-
unless env["PATH_INFO"].index(@config.base_path) == 0
|
12
|
-
@app.call(env)
|
11
|
+
unless env["PATH_INFO"].index(@config.base_path) == 0
|
12
|
+
response = @app.call(env)
|
13
13
|
else
|
14
|
-
|
15
|
-
return extract_documentation(env)
|
16
|
-
rescue => e
|
17
|
-
[500, {}, e.backtrace.join("\n")]
|
18
|
-
end
|
14
|
+
response = extract_documentation(env)
|
19
15
|
end
|
16
|
+
response
|
20
17
|
end
|
21
18
|
|
22
19
|
private
|
@@ -25,6 +22,10 @@ module Baurets
|
|
25
22
|
require 'yaml'
|
26
23
|
require 'RedCloth'
|
27
24
|
|
25
|
+
def verify_path(env)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
28
29
|
def extract_documentation(env)
|
29
30
|
path = env["PATH_INFO"]
|
30
31
|
path = path.gsub(@config.base_path, '')
|
@@ -43,40 +44,47 @@ module Baurets
|
|
43
44
|
controller_actions << [verb, relate_action_to_method(path_parts, verb)]
|
44
45
|
end
|
45
46
|
controller_actions.delete_if {|pair| pair[1].empty? }
|
46
|
-
|
47
|
-
|
48
|
-
file = File.join(RAILS_ROOT, "app", "controllers", controller_name + ".rb")
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
47
|
+
controller_name = (::Baurets::Optionsful::Introspections.discover_controller_name(path_parts) + "_controller" ) if ::Baurets::Optionsful::Introspections.discover_controller_name(path_parts)
|
48
|
+
file = ""
|
49
|
+
file = File.join(RAILS_ROOT, "app", "controllers", controller_name + ".rb") if controller_name
|
50
|
+
if File.exist? file
|
51
|
+
controller_class = controller_name.camelize
|
52
|
+
service_doc = extract_comments_above(file, find_line_for(file, controller_class, :class))
|
53
|
+
methods_docs = []
|
54
|
+
controller_actions.each do |info|
|
55
|
+
methods_docs << [info, extract_comments_above(file, find_line_for(file, info[1], :method)).join("\n")]
|
56
|
+
end
|
57
|
+
body = build_html(service_doc, methods_docs)
|
58
|
+
[200, {"Content-Type" => "text/html"}, body]
|
59
|
+
else
|
60
|
+
[404, {}, " "]
|
56
61
|
end
|
57
|
-
|
58
|
-
body = build_html(service_doc, methods_docs)
|
59
|
-
|
60
|
-
[200, {"Content-Type" => "text/html"}, body]
|
61
62
|
end
|
62
63
|
|
63
|
-
|
64
|
-
def build_html(comment, methods)
|
65
|
-
comments = comment.join("\n").gsub(/^#+\s/, '')
|
66
|
-
resource = YAML::parse(comments)
|
64
|
+
def build_html(srvc, methods)
|
67
65
|
html = "<html><head></head><body>"
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
66
|
+
comments = srvc.join("\n").gsub(/^#+\s/, '')
|
67
|
+
srvc_doc = YAML::parse(comments)
|
68
|
+
if srvc_doc && srvc_doc["service"]
|
69
|
+
resource_title = srvc_doc["service"]["title"].value
|
70
|
+
title = "h1. " + resource_title.to_s if resource_title
|
71
|
+
html += RedCloth.new(title).to_html
|
72
|
+
html += RedCloth.new("#{srvc_doc["service"]["description"].value}").to_html
|
73
|
+
html += "\n<link rel=\"replies\" href=\"\" </link>"
|
74
|
+
methods.each do |meth|
|
75
|
+
meth_verb = meth[0][0]
|
76
|
+
method_comms = meth[1].gsub(/^#+\s/, '') unless meth[1].empty?
|
77
|
+
resource = YAML::parse(method_comms)
|
78
|
+
html += RedCloth.new("h2. " + meth_verb).to_html
|
79
|
+
if resource && resource["resource"]
|
80
|
+
html += RedCloth.new(resource["resource"]["title"].value).to_html
|
81
|
+
html += RedCloth.new(resource["resource"]["identifier"].value).to_html
|
82
|
+
else
|
83
|
+
html += RedCloth.new("Could not find or understand any annotated metadata related to method #{meth_verb}.").to_html
|
84
|
+
end
|
85
|
+
end
|
86
|
+
else
|
87
|
+
html += RedCloth.new("Could not understand anything.").to_html
|
80
88
|
end
|
81
89
|
html += "</body></html>"
|
82
90
|
html
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe Baurets::Optionsful::Config do
|
5
|
+
|
6
|
+
include Rack::Test::Methods
|
7
|
+
|
8
|
+
describe "Config carries specific settings" do
|
9
|
+
|
10
|
+
describe "by default, try to find the custom configuration file" do
|
11
|
+
|
12
|
+
it "if the custom configuration file exist, try to load settings from it" do
|
13
|
+
config = Baurets::Optionsful::Config.new( {:file => File.join(File.dirname(__FILE__), 'fixtures', 'optionsful.yml'), :environment => "test" })
|
14
|
+
config.base_path.should == "/test"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "if the custom configuration file exist and is not valid, keep the default settings" do
|
18
|
+
config = Baurets::Optionsful::Config.new( {:file => File.join(File.dirname(__FILE__), 'fixtures', 'optionsful_bug.yml'), :environment => "test" })
|
19
|
+
config.base_path.should == "/optionsful"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "if no configuration file is informed or found, do load the default settings" do
|
23
|
+
config = Baurets::Optionsful::Config.new
|
24
|
+
config.base_path.should == "/optionsful"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "if RAILS_ROOT is defined, look for the custom configuration file on its config folder" do
|
28
|
+
Baurets::Optionsful::Config.const_set(:RAILS_ROOT, File.dirname(__FILE__))
|
29
|
+
config = Baurets::Optionsful::Config.new
|
30
|
+
config.base_path.should == "/optionsful"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "if a custom configuration file is informed "
|
36
|
+
|
37
|
+
it "and does not exist, keep default settings" do
|
38
|
+
config = Baurets::Optionsful::Config.new( {:file => File.join(File.dirname(__FILE__), 'fixtures', 'optionsful_xxx.yml'), :environment => "test" })
|
39
|
+
config.base_path.should == "/optionsful"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -5,8 +5,9 @@ describe Baurets::Optionsful::Documentator do
|
|
5
5
|
|
6
6
|
include Rack::Test::Methods
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
Baurets::Optionsful::Documentator.send(:remove_const, :RAILS_ROOT) if Baurets::Optionsful::Documentator.const_defined?(:RAILS_ROOT)
|
9
|
+
Baurets::Optionsful::Documentator.const_set(:RAILS_ROOT, File.join(File.dirname(__FILE__), 'samples' ) )
|
10
|
+
base_path = ::Baurets::Optionsful::Config.new.base_path
|
10
11
|
|
11
12
|
describe "as a Rack middleware" do
|
12
13
|
|
@@ -14,13 +15,19 @@ config = ::Baurets::Optionsful::Config.new
|
|
14
15
|
assert ::Baurets::Optionsful::Documentator.new(app).respond_to? :call
|
15
16
|
end
|
16
17
|
|
18
|
+
before do
|
19
|
+
ActionController::Routing::Routes.draw do |map|
|
20
|
+
map.resources :posts, :has_many => :comments
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
17
24
|
it "takes exactly one argument, (the environment) and returns an Array;" do
|
18
|
-
response = ::Baurets::Optionsful::Documentator.new(app).call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" =>
|
25
|
+
response = ::Baurets::Optionsful::Documentator.new(app).call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => (base_path + "/posts")}))
|
19
26
|
assert response.kind_of?(Array)
|
20
27
|
end
|
21
28
|
|
22
29
|
it "the returned Array must have exactly three values: the status, the headers and the body;" do
|
23
|
-
response = ::Baurets::Optionsful::Documentator.new(app).call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" =>
|
30
|
+
response = ::Baurets::Optionsful::Documentator.new(app).call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => (base_path + "/posts")}))
|
24
31
|
assert response.size.should == 3
|
25
32
|
assert response[0].kind_of? Fixnum
|
26
33
|
assert response[1].kind_of? Hash
|
@@ -37,4 +44,74 @@ config = ::Baurets::Optionsful::Config.new
|
|
37
44
|
|
38
45
|
end
|
39
46
|
|
47
|
+
describe "extracts metadata information about a resource" do
|
48
|
+
|
49
|
+
describe "MUST override Rails routing recognition successfully" do
|
50
|
+
|
51
|
+
before(:all) do
|
52
|
+
ActionController::Routing::Routes.draw do |map|
|
53
|
+
map.resources :posts, :has_many => :comments
|
54
|
+
map.resources :notes
|
55
|
+
map.resources :stuff
|
56
|
+
map.resources :trips
|
57
|
+
map.resources :teams
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "may let the request go through if base path doesn't match" do
|
62
|
+
pending
|
63
|
+
# req_path = "/xyz"
|
64
|
+
# response = http_get_request(req_path)
|
65
|
+
# assert response[0].kind_of? Fixnum
|
66
|
+
# assert response[0].should_not == 500
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
it "MAY find proper structured information and build an html response" do
|
71
|
+
Baurets::Optionsful::Documentator.send(:remove_const, :RAILS_ROOT) if Baurets::Optionsful::Documentator.const_defined?(:RAILS_ROOT)
|
72
|
+
Baurets::Optionsful::Documentator.const_set(:RAILS_ROOT, File.join(File.dirname(__FILE__), 'samples' ) )
|
73
|
+
req_path = base_path + "/posts"
|
74
|
+
response = http_get_request(req_path)
|
75
|
+
|
76
|
+
assert response[0].kind_of? Fixnum
|
77
|
+
assert response[0].should == 200
|
78
|
+
end
|
79
|
+
|
80
|
+
it "MAY NOT find proper structured information and build an html response" do
|
81
|
+
req_path = base_path + "/notes"
|
82
|
+
response = http_get_request(req_path)
|
83
|
+
assert response.kind_of?(Array)
|
84
|
+
assert response[0].kind_of? Fixnum
|
85
|
+
end
|
86
|
+
|
87
|
+
it "MAY NOT find controller file and build an html response" do
|
88
|
+
req_path = base_path + "/stuff"
|
89
|
+
response = http_get_request(req_path)
|
90
|
+
assert response.kind_of?(Array)
|
91
|
+
assert response[0].kind_of? Fixnum
|
92
|
+
end
|
93
|
+
|
94
|
+
it "MAY NOT understand anything" do
|
95
|
+
req_path = base_path + "/trips"
|
96
|
+
response = http_get_request(req_path)
|
97
|
+
assert response.kind_of?(Array)
|
98
|
+
assert response[0].kind_of? Fixnum
|
99
|
+
end
|
100
|
+
|
101
|
+
it "MAY NOT understand anything" do
|
102
|
+
req_path = base_path + "/teams"
|
103
|
+
response = http_get_request(req_path)
|
104
|
+
assert response.kind_of?(Array)
|
105
|
+
assert response[0].kind_of? Fixnum
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
after(:all) do
|
110
|
+
ActionController::Routing::Routes.reload!
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
40
117
|
end
|
@@ -5,13 +5,6 @@ describe Baurets::Optionsful::Server do
|
|
5
5
|
|
6
6
|
include Rack::Test::Methods
|
7
7
|
|
8
|
-
before(:all) do
|
9
|
-
ActionController::Routing::Routes.draw do |map|
|
10
|
-
map.resources :posts, :has_many => :comments
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
8
|
describe "as a Rack middleware" do
|
16
9
|
|
17
10
|
it "is a Ruby object that responds to call;" do
|
@@ -31,6 +24,12 @@ describe Baurets::Optionsful::Server do
|
|
31
24
|
assert response[2].kind_of? String
|
32
25
|
end
|
33
26
|
|
27
|
+
before do
|
28
|
+
ActionController::Routing::Routes.draw do |map|
|
29
|
+
map.resources :posts, :has_many => :comments
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
34
33
|
it "must be nice, acting somewhere on a Rack middleware stack." do
|
35
34
|
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
|
36
35
|
assert response.size.should == 3
|
@@ -40,14 +39,27 @@ describe Baurets::Optionsful::Server do
|
|
40
39
|
assert response[1]["Allow"]
|
41
40
|
end
|
42
41
|
|
42
|
+
it "must let the request go through the stack, if it has nothing to it" do
|
43
|
+
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => "/lobster"}))
|
44
|
+
assert response.size.should == 3
|
45
|
+
assert response[0].kind_of? Fixnum
|
46
|
+
assert response[0].should == 200
|
47
|
+
assert response[1].kind_of? Hash
|
48
|
+
end
|
49
|
+
|
43
50
|
end
|
44
51
|
|
52
|
+
describe "is intended to provide HTTP OPTIONS calls for Rails RESTful resources" do
|
45
53
|
|
46
|
-
|
54
|
+
describe "to collect the allowed HTTP methods, it overrides Rails routing recognition, so it must understand" do
|
47
55
|
|
48
|
-
|
56
|
+
describe "the default Rails resource routing: " do
|
49
57
|
|
50
|
-
|
58
|
+
before(:all) do
|
59
|
+
ActionController::Routing::Routes.draw do |map|
|
60
|
+
map.resources :posts, :has_many => :comments
|
61
|
+
end
|
62
|
+
end
|
51
63
|
|
52
64
|
it "the index action displays a list of all posts in response of a GET request;" do
|
53
65
|
response = http_options_request("/posts")
|
@@ -90,36 +102,68 @@ describe Baurets::Optionsful::Server do
|
|
90
102
|
assert response.kind_of?(Array)
|
91
103
|
assert allows?(response[1], "DELETE")
|
92
104
|
end
|
93
|
-
|
105
|
+
|
94
106
|
it "not found a path" do
|
95
107
|
response = http_options_request("/sblingers/sblongers")
|
96
108
|
assert response.kind_of?(Array)
|
97
109
|
assert response[0].should == 404
|
98
110
|
end
|
99
|
-
|
111
|
+
|
112
|
+
# Note that extension relation types are REQUIRED to be absolute URIs
|
113
|
+
# in Link headers, and MUST be quoted if they contain a semicolon (";")
|
114
|
+
# or comma (",") (as these characters are used as delimiters in the
|
115
|
+
# header itself).
|
116
|
+
|
117
|
+
it "the Link header MUST be quoted if it contains a semicolon or comma" do
|
118
|
+
response = http_options_request("/posts")
|
119
|
+
assert response.kind_of?(Array)
|
120
|
+
link = response[1]["Link"]
|
121
|
+
|
122
|
+
assert link.should =~ /\A"{1}.+"\z/
|
123
|
+
|
124
|
+
end
|
125
|
+
|
100
126
|
it "not finding a path, pretend you're dead and.. let it goes through" do
|
101
127
|
pending
|
102
128
|
end
|
103
129
|
|
104
130
|
end
|
105
131
|
|
106
|
-
|
132
|
+
describe "must understand Rails named routes" do
|
107
133
|
|
108
|
-
|
134
|
+
before(:each) do
|
135
|
+
ActionController::Routing::Routes.draw do |map|
|
136
|
+
map.login 'login', :controller => 'accounts', :action => 'login'
|
137
|
+
end
|
138
|
+
end
|
109
139
|
|
110
|
-
|
140
|
+
it "must understand" do
|
141
|
+
pending
|
142
|
+
end
|
111
143
|
|
112
|
-
it " method GET example" do
|
113
|
-
complex_env = mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => "/lobster" })
|
114
|
-
response = fake_opts_app.call(complex_env)
|
115
|
-
assert response.kind_of?(Array)
|
116
|
-
assert response.size.should == 3
|
117
|
-
end
|
118
144
|
|
119
|
-
end
|
120
145
|
|
121
|
-
|
122
|
-
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "Rails custom route" do
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "Rails route globbing" do
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "Pretty URLs" do
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "Regular Expressions and parameters" do
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
123
164
|
end
|
124
165
|
|
125
166
|
end
|
167
|
+
|
168
|
+
|
169
|
+
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# ---
|
2
|
+
# service:
|
3
|
+
# title: Post comments controller
|
4
|
+
# entrypoint: /posts/:post/comments
|
5
|
+
# support: kayaman@baurets.net
|
6
|
+
# description: Comments Service allow you say shit about anything you dislike!
|
7
|
+
class CommentsController < ApplicationController
|
8
|
+
|
9
|
+
# ---
|
10
|
+
# resource:
|
11
|
+
# title: list
|
12
|
+
# identifier: /posts/{:post}/comments
|
13
|
+
# support: kayaman@baurets.net
|
14
|
+
# description: Create new comments over a post instance.
|
15
|
+
# source-link: research
|
16
|
+
# alternates:
|
17
|
+
# - one
|
18
|
+
# - two
|
19
|
+
# representation:
|
20
|
+
# media-types:
|
21
|
+
# - application/xml
|
22
|
+
# - application/json
|
23
|
+
# last-modified: 2010-07-23
|
24
|
+
# control:
|
25
|
+
# cache: no-cache
|
26
|
+
def index
|
27
|
+
end
|
28
|
+
|
29
|
+
# ---
|
30
|
+
# resource:
|
31
|
+
# title: create
|
32
|
+
# identifier: /
|
33
|
+
# support: kayaman@baurets.net
|
34
|
+
# description: Create new posts.
|
35
|
+
# source-link: research
|
36
|
+
# alternates:
|
37
|
+
# - one
|
38
|
+
# - two
|
39
|
+
# representation:
|
40
|
+
# media-types:
|
41
|
+
# - application/xml
|
42
|
+
# - application/json
|
43
|
+
# last-modified: 2010-07-23
|
44
|
+
# control:
|
45
|
+
# cache: no-cache
|
46
|
+
def show
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def new
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def update
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def delete
|
59
|
+
end
|
60
|
+
|
61
|
+
# ---
|
62
|
+
# resource:
|
63
|
+
# title: create
|
64
|
+
# identifier: /
|
65
|
+
# support: kayaman@baurets.net
|
66
|
+
# description: Create new posts.
|
67
|
+
# source-link: research
|
68
|
+
# alternates:
|
69
|
+
# - one
|
70
|
+
# - two
|
71
|
+
# representation:
|
72
|
+
# media-types:
|
73
|
+
# - application/xml
|
74
|
+
# - application/json
|
75
|
+
# last-modified: 2010-07-23
|
76
|
+
# control:
|
77
|
+
# cache: no-cache
|
78
|
+
def create
|
79
|
+
@post = Post.find(params[:post_id])
|
80
|
+
@comment = @post.comments.create!(params[:comment])
|
81
|
+
respond_to do |format|
|
82
|
+
format.html { redirect_to @post }
|
83
|
+
format.js
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# ---
|
2
|
+
# service:
|
3
|
+
# title: Posts front controller
|
4
|
+
# entrypoint: /posts
|
5
|
+
# support: kayaman@baurets.net
|
6
|
+
# description: The Posts sevices let you list, create, update, and delete Posts from our application.
|
7
|
+
class PostsController < ApplicationController
|
8
|
+
before_filter :authenticate, :except => [:index, :show]
|
9
|
+
|
10
|
+
# ---
|
11
|
+
# resource:
|
12
|
+
# title: Listing
|
13
|
+
# identifier: /
|
14
|
+
# support: kayaman@baurets.net
|
15
|
+
# description: List posts.
|
16
|
+
# source-link: research
|
17
|
+
# alternates:
|
18
|
+
# - one
|
19
|
+
# - two
|
20
|
+
# representation:
|
21
|
+
# media-types:
|
22
|
+
# - application/xml
|
23
|
+
# - application/json
|
24
|
+
# last-modified: 2010-07-23
|
25
|
+
# control:
|
26
|
+
# cache: cache-control
|
27
|
+
def index
|
28
|
+
@posts = Post.find(:all)
|
29
|
+
|
30
|
+
respond_to do |format|
|
31
|
+
format.html # index.html.erb
|
32
|
+
format.xml { render :xml => @posts }
|
33
|
+
format.json { render :json => @posts }
|
34
|
+
format.atom
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# ---
|
39
|
+
# resource:
|
40
|
+
# title: Posts front controller
|
41
|
+
# identifier: /posts
|
42
|
+
# support: kayaman@baurets.net
|
43
|
+
# description: Retuns all posts.
|
44
|
+
# representation:
|
45
|
+
# media-types:
|
46
|
+
# - application/xml
|
47
|
+
# - application/json
|
48
|
+
# last-modified: 2010-07-23
|
49
|
+
def show
|
50
|
+
@post = Post.find(params[:id])
|
51
|
+
|
52
|
+
respond_to do |format|
|
53
|
+
format.html # show.html.erb
|
54
|
+
format.xml { render :xml => @post }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# ---
|
59
|
+
# resource:
|
60
|
+
# title: Posts front controller
|
61
|
+
# identifier: /posts
|
62
|
+
# support: kayaman@baurets.net
|
63
|
+
# description: Retuns all posts.
|
64
|
+
# representation:
|
65
|
+
# media-types:
|
66
|
+
# - application/xml
|
67
|
+
# - application/json
|
68
|
+
# last-modified: 2010-07-23
|
69
|
+
def new
|
70
|
+
@post = Post.new
|
71
|
+
|
72
|
+
respond_to do |format|
|
73
|
+
format.html # new.html.erb
|
74
|
+
format.xml { render :xml => @post }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# ---
|
79
|
+
# resource:
|
80
|
+
# title: create
|
81
|
+
# identifier: /
|
82
|
+
# support: kayaman@baurets.net
|
83
|
+
# description: Create new posts.
|
84
|
+
# source-link: research
|
85
|
+
# alternates:
|
86
|
+
# - one
|
87
|
+
# - two
|
88
|
+
# representation:
|
89
|
+
# media-types:
|
90
|
+
# - application/xml
|
91
|
+
# - application/json
|
92
|
+
# last-modified: 2010-07-23
|
93
|
+
# control:
|
94
|
+
# cache: no-cache
|
95
|
+
def edit
|
96
|
+
@post = Post.find(params[:id])
|
97
|
+
end
|
98
|
+
|
99
|
+
# ---
|
100
|
+
# resource:
|
101
|
+
# title: create
|
102
|
+
# identifier: /
|
103
|
+
# support: kayaman@baurets.net
|
104
|
+
# description: Create new posts.
|
105
|
+
# source-link: research
|
106
|
+
# alternates:
|
107
|
+
# - one
|
108
|
+
# - two
|
109
|
+
# representation:
|
110
|
+
# media-types:
|
111
|
+
# - application/xml
|
112
|
+
# - application/json
|
113
|
+
# last-modified: 2010-07-23
|
114
|
+
# control:
|
115
|
+
# cache: no-cache
|
116
|
+
def create
|
117
|
+
@post = Post.new(params[:post])
|
118
|
+
|
119
|
+
respond_to do |format|
|
120
|
+
if @post.save
|
121
|
+
flash[:notice] = 'Post was successfully created.'
|
122
|
+
format.html { redirect_to(@post) }
|
123
|
+
format.xml { render :xml => @post, :status => :created, :location => @post }
|
124
|
+
else
|
125
|
+
format.html { render :action => "new" }
|
126
|
+
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# ---
|
132
|
+
# resource:
|
133
|
+
# title: Posts front controller
|
134
|
+
# identifier: /posts
|
135
|
+
# support: kayaman@baurets.net
|
136
|
+
# description: Retuns all posts.
|
137
|
+
# representation:
|
138
|
+
# media-types:
|
139
|
+
# - application/xml
|
140
|
+
# - application/json
|
141
|
+
# last-modified: 2010-07-23
|
142
|
+
def update
|
143
|
+
@post = Post.find(params[:id])
|
144
|
+
|
145
|
+
respond_to do |format|
|
146
|
+
if @post.update_attributes(params[:post])
|
147
|
+
flash[:notice] = 'Post was successfully updated.'
|
148
|
+
format.html { redirect_to(@post) }
|
149
|
+
format.xml { head :ok }
|
150
|
+
else
|
151
|
+
format.html { render :action => "edit" }
|
152
|
+
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# ---
|
158
|
+
# resource:
|
159
|
+
# title: Posts front controller
|
160
|
+
# identifier: /posts
|
161
|
+
# support: kayaman@baurets.net
|
162
|
+
# description: Retuns all posts.
|
163
|
+
# representation:
|
164
|
+
# media-types:
|
165
|
+
# - application/xml
|
166
|
+
# - application/json
|
167
|
+
# last-modified: 2010-07-23
|
168
|
+
def destroy
|
169
|
+
@post = Post.find(params[:id])
|
170
|
+
@post.destroy
|
171
|
+
|
172
|
+
respond_to do |format|
|
173
|
+
format.html { redirect_to(posts_url) }
|
174
|
+
format.xml { head :ok }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def authenticate
|
181
|
+
authenticate_or_request_with_http_basic do |name, password|
|
182
|
+
name == "admin" && password == "secret"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# ---
|
2
|
+
# service:
|
3
|
+
# title: Teams controller
|
4
|
+
# entrypoint: /posts/:post/comments
|
5
|
+
# support: kayaman@baurets.net
|
6
|
+
# description: Comments Service allow you say shit about anything you dislike!
|
7
|
+
class TripsController < ApplicationController
|
8
|
+
|
9
|
+
# !! something wrong ? &
|
10
|
+
# & ^% !@#
|
11
|
+
def index
|
12
|
+
end
|
13
|
+
|
14
|
+
def show
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def new
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def update
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def delete
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def create
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
##
|
2
|
+
# sjdhsdjhsdhhjdhjjdhsjhsdhsdjhjshdjhsdshd
|
3
|
+
class TripsController < ApplicationController
|
4
|
+
|
5
|
+
# ---
|
6
|
+
# resource:
|
7
|
+
# title: list
|
8
|
+
# identifier: /posts/{:post}/comments
|
9
|
+
# support: kayaman@baurets.net
|
10
|
+
# description: Create new comments over a post instance.
|
11
|
+
# source-link: research
|
12
|
+
# alternates:
|
13
|
+
# - one
|
14
|
+
# - two
|
15
|
+
# representation:
|
16
|
+
# media-types:
|
17
|
+
# - application/xml
|
18
|
+
# - application/json
|
19
|
+
# last-modified: 2010-07-23
|
20
|
+
# control:
|
21
|
+
# cache: no-cache
|
22
|
+
def index
|
23
|
+
end
|
24
|
+
|
25
|
+
# ---
|
26
|
+
# resource:
|
27
|
+
# title: create
|
28
|
+
# identifier: /
|
29
|
+
# support: kayaman@baurets.net
|
30
|
+
# description: Create new posts.
|
31
|
+
# source-link: research
|
32
|
+
# alternates:
|
33
|
+
# - one
|
34
|
+
# - two
|
35
|
+
# representation:
|
36
|
+
# media-types:
|
37
|
+
# - application/xml
|
38
|
+
# - application/json
|
39
|
+
# last-modified: 2010-07-23
|
40
|
+
# control:
|
41
|
+
# cache: no-cache
|
42
|
+
def show
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def new
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def update
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def delete
|
55
|
+
end
|
56
|
+
|
57
|
+
# ---
|
58
|
+
# resource:
|
59
|
+
# title: create
|
60
|
+
# identifier: /
|
61
|
+
# support: kayaman@baurets.net
|
62
|
+
# description: Create new posts.
|
63
|
+
# source-link: research
|
64
|
+
# alternates:
|
65
|
+
# - one
|
66
|
+
# - two
|
67
|
+
# representation:
|
68
|
+
# media-types:
|
69
|
+
# - application/xml
|
70
|
+
# - application/json
|
71
|
+
# last-modified: 2010-07-23
|
72
|
+
# control:
|
73
|
+
# cache: no-cache
|
74
|
+
def create
|
75
|
+
@post = Post.find(params[:post_id])
|
76
|
+
@comment = @post.comments.create!(params[:comment])
|
77
|
+
respond_to do |format|
|
78
|
+
format.html { redirect_to @post }
|
79
|
+
format.js
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -73,6 +73,12 @@ DEFAULT_ENV = { "rack.version" => Rack::VERSION, "rack.input" => StringIO.new, "
|
|
73
73
|
response = Baurets::Optionsful::Server.new(app).call(complex_env)
|
74
74
|
end
|
75
75
|
|
76
|
+
def http_get_request(path)
|
77
|
+
complex_env = mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => path })
|
78
|
+
response = Baurets::Optionsful::Documentator.new(app).call(complex_env)
|
79
|
+
end
|
80
|
+
|
81
|
+
|
76
82
|
def allows?(headers, method)
|
77
83
|
headers["Allow"].include?(method)
|
78
84
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: optionsful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 8
|
10
|
+
version: 0.1.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marco Antonio Gonzalez Junior
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-26 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
version: 4.2.2
|
35
35
|
type: :runtime
|
36
36
|
version_requirements: *id001
|
37
|
-
description: Optionsful provide dynamic information
|
37
|
+
description: Optionsful provide dynamic information and HTTP's OPTION method support.
|
38
38
|
email: kayaman@baurets.net
|
39
39
|
executables: []
|
40
40
|
|
@@ -45,21 +45,29 @@ extra_rdoc_files: []
|
|
45
45
|
files:
|
46
46
|
- README.textile
|
47
47
|
- MIT-LICENSE
|
48
|
-
- lib/baurets/optionsful/server.rb
|
49
|
-
- rails/init.rb
|
50
|
-
- lib/tasks/optionsful.rake
|
51
48
|
- Rakefile
|
52
|
-
-
|
53
|
-
- spec/spec.opts
|
54
|
-
- spec/spec_helper.rb
|
49
|
+
- lib/optionsful.rb
|
55
50
|
- lib/baurets/optionsful/documentator.rb
|
51
|
+
- lib/baurets/optionsful/server.rb
|
56
52
|
- lib/baurets/optionsful/introspections.rb
|
57
|
-
- lib/baurets/optionsful/version.rb
|
58
53
|
- lib/baurets/optionsful/config.rb
|
59
|
-
- lib/optionsful.rb
|
54
|
+
- lib/baurets/optionsful/version.rb
|
55
|
+
- lib/tasks/optionsful.rake
|
56
|
+
- rails/init.rb
|
57
|
+
- spec/fixtures/optionsful.yml
|
58
|
+
- spec/fixtures/optionsful_bug.yml
|
59
|
+
- spec/samples/app/controllers/comments_controller.rb
|
60
|
+
- spec/samples/app/controllers/notes_controller.rb
|
61
|
+
- spec/samples/app/controllers/posts_controller.rb
|
62
|
+
- spec/samples/app/controllers/teams_controller.rb
|
63
|
+
- spec/samples/app/controllers/trips_controller.rb
|
64
|
+
- spec/optionsful_server_spec.rb
|
60
65
|
- spec/optionsful_documentator_spec.rb
|
66
|
+
- spec/optionsful_config_spec.rb
|
67
|
+
- spec/spec.opts
|
68
|
+
- spec/spec_helper.rb
|
61
69
|
has_rdoc: true
|
62
|
-
homepage: http://optionsful
|
70
|
+
homepage: http://github.com/kayaman/optionsful
|
63
71
|
licenses: []
|
64
72
|
|
65
73
|
post_install_message:
|
@@ -91,6 +99,6 @@ rubyforge_project:
|
|
91
99
|
rubygems_version: 1.3.7
|
92
100
|
signing_key:
|
93
101
|
specification_version: 3
|
94
|
-
summary: Optionsful
|
102
|
+
summary: Optionsful gives HTTP's OPTION method support for Ruby on Rails applications. Also extract dynamic information for easily documenting RESTful web services.
|
95
103
|
test_files: []
|
96
104
|
|