optionsful 0.1.8 → 0.2.3
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/MIT-LICENSE +1 -1
- data/README.textile +30 -20
- data/Rakefile +1 -1
- data/lib/baurets/optionsful/introspections.rb +11 -18
- data/lib/baurets/optionsful/server.rb +5 -0
- data/lib/baurets/optionsful/version.rb +2 -2
- data/lib/optionsful.rb +0 -1
- data/lib/tasks/optionsful.rake +8 -4
- data/rails/init.rb +7 -1
- data/samples/optionsful.yml +14 -0
- data/spec/optionsful_config_spec.rb +8 -12
- data/spec/optionsful_server_spec.rb +236 -70
- data/spec/spec_helper.rb +7 -22
- metadata +10 -31
- data/lib/baurets/optionsful/documentator.rb +0 -158
- data/spec/optionsful_documentator_spec.rb +0 -117
- data/spec/samples/app/controllers/comments_controller.rb +0 -86
- data/spec/samples/app/controllers/notes_controller.rb +0 -6
- data/spec/samples/app/controllers/posts_controller.rb +0 -185
- data/spec/samples/app/controllers/teams_controller.rb +0 -33
- data/spec/samples/app/controllers/trips_controller.rb +0 -82
@@ -5,7 +5,7 @@ describe Baurets::Optionsful::Server do
|
|
5
5
|
|
6
6
|
include Rack::Test::Methods
|
7
7
|
|
8
|
-
|
8
|
+
context "as a Rack middleware" do
|
9
9
|
|
10
10
|
it "is a Ruby object that responds to call;" do
|
11
11
|
assert ::Baurets::Optionsful::Server.new(app).respond_to? :call
|
@@ -30,7 +30,7 @@ describe Baurets::Optionsful::Server do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
it "must be nice, acting somewhere on a Rack middleware stack
|
33
|
+
it "must be nice, acting somewhere on a Rack middleware stack;" do
|
34
34
|
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => "/posts"}))
|
35
35
|
assert response.size.should == 3
|
36
36
|
assert response[0].kind_of? Fixnum
|
@@ -39,7 +39,7 @@ describe Baurets::Optionsful::Server do
|
|
39
39
|
assert response[1]["Allow"]
|
40
40
|
end
|
41
41
|
|
42
|
-
it "must let the request go through the stack, if it has nothing to it" do
|
42
|
+
it "must let the request go through the stack, if it has nothing to it!" do
|
43
43
|
response = fake_opts_app.call(mock_env({"REQUEST_METHOD" => "GET", "PATH_INFO" => "/lobster"}))
|
44
44
|
assert response.size.should == 3
|
45
45
|
assert response[0].kind_of? Fixnum
|
@@ -49,114 +49,281 @@ describe Baurets::Optionsful::Server do
|
|
49
49
|
|
50
50
|
end
|
51
51
|
|
52
|
-
|
52
|
+
context "as an interpreter for HTTP OPTIONS requests, MUST recognize the Rails" do
|
53
53
|
|
54
|
-
describe "
|
54
|
+
describe "default resource routing" do
|
55
|
+
#Sample resource route (maps HTTP verbs to controller actions automatically)
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
ActionController::Routing::Routes.draw do |map|
|
60
|
-
map.resources :posts, :has_many => :comments
|
61
|
-
end
|
57
|
+
before(:all) do
|
58
|
+
ActionController::Routing::Routes.draw do |map|
|
59
|
+
map.resources :posts, :has_many => :comments
|
62
60
|
end
|
61
|
+
end
|
63
62
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
it "the index action displays a list of all posts in response of a GET request" do
|
64
|
+
response = http_options_request("/posts")
|
65
|
+
assert response.kind_of?(Array)
|
66
|
+
assert allows?(response[1], "GET")
|
67
|
+
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
it "the new action return from a GET request an HTML form for creating a new post" do
|
70
|
+
response = http_options_request("/posts/new")
|
71
|
+
assert response.kind_of?(Array)
|
72
|
+
assert allows?(response[1], "GET")
|
73
|
+
end
|
75
74
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
75
|
+
it "the create action uses POST to create a new post instance" do
|
76
|
+
response = http_options_request("/posts")
|
77
|
+
assert response.kind_of?(Array)
|
78
|
+
assert allows?(response[1], "POST")
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
81
|
+
it "the show action display a specific post in response of a GET request" do
|
82
|
+
response = http_options_request("/posts/1")
|
83
|
+
assert response.kind_of?(Array)
|
84
|
+
assert allows?(response[1], "GET")
|
85
|
+
end
|
86
|
+
|
87
|
+
it "the edit action return an HTML form for editing a post in response of a GET request" do
|
88
|
+
response = http_options_request("/posts/1/edit")
|
89
|
+
assert response.kind_of?(Array)
|
90
|
+
assert allows?(response[1], "GET")
|
91
|
+
end
|
92
|
+
|
93
|
+
it "the update action uses PUT to update a specific post" do
|
94
|
+
response = http_options_request("/posts/1")
|
95
|
+
assert response.kind_of?(Array)
|
96
|
+
assert allows?(response[1], "PUT")
|
97
|
+
end
|
98
|
+
|
99
|
+
it "the destroy action uses DELETE to delete a specific post" do
|
100
|
+
response = http_options_request("/posts/1")
|
101
|
+
assert response.kind_of?(Array)
|
102
|
+
assert allows?(response[1], "DELETE")
|
103
|
+
end
|
104
|
+
|
105
|
+
it "not finding a path, return 404 Not Found" do
|
106
|
+
response = http_options_request("/sblingers/sblongers")
|
107
|
+
assert response.kind_of?(Array)
|
108
|
+
assert response[0].should be 404
|
109
|
+
end
|
110
|
+
|
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
|
+
it "the Link header MUST be quoted if it contains a semicolon or comma" do
|
117
|
+
response = http_options_request("/posts")
|
118
|
+
assert response.kind_of?(Array)
|
119
|
+
link = response[1]["Link"]
|
120
|
+
assert link.should =~ /\A"{1}.+"\z/
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
87
124
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
125
|
+
describe "named routes" do
|
126
|
+
|
127
|
+
before(:each) do
|
128
|
+
ActionController::Routing::Routes.draw do |map|
|
129
|
+
map.login 'login', :controller => 'accounts', :action => 'login'
|
92
130
|
end
|
131
|
+
end
|
93
132
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
133
|
+
it "should work" do
|
134
|
+
response = http_options_request("/login")
|
135
|
+
assert response.kind_of?(Array)
|
136
|
+
assert response[0].should be 204
|
137
|
+
assert allows?(response[1], "GET") # WTF? return ANY?!? ;p
|
138
|
+
end
|
139
|
+
|
140
|
+
after(:all) do
|
141
|
+
ActionController::Routing::Routes.reload!
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "route globbing" do
|
147
|
+
|
148
|
+
before(:all) do
|
149
|
+
ActionController::Routing::Routes.draw do |map|
|
150
|
+
map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
|
98
151
|
end
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should work" do
|
155
|
+
pending "What the hell is that?"
|
156
|
+
response = http_options_request("/post/path")
|
157
|
+
assert response.kind_of?(Array)
|
158
|
+
assert response[0].should_not be 404
|
159
|
+
end
|
160
|
+
|
161
|
+
after(:all) do
|
162
|
+
ActionController::Routing::Routes.reload!
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
99
166
|
|
100
|
-
|
101
|
-
response = http_options_request("/posts/1")
|
102
|
-
assert response.kind_of?(Array)
|
103
|
-
assert allows?(response[1], "DELETE")
|
104
|
-
end
|
167
|
+
describe "route conditions" do
|
105
168
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
169
|
+
before(:all) do
|
170
|
+
ActionController::Routing::Routes.draw do |map|
|
171
|
+
map.connect 'post/:id', :controller => 'posts', :action => 'show', :conditions => { :method => :get }
|
172
|
+
map.connect 'post/:id', :controller => 'posts', :action => 'create_comment', :conditions => { :method => :post }
|
110
173
|
end
|
174
|
+
end
|
111
175
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
176
|
+
it "should work" do
|
177
|
+
response = http_options_request("/post/123")
|
178
|
+
assert response.kind_of?(Array)
|
179
|
+
assert allows?(response[1], "GET")
|
180
|
+
assert allows?(response[1], "POST")
|
181
|
+
end
|
116
182
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
183
|
+
after(:all) do
|
184
|
+
ActionController::Routing::Routes.reload!
|
185
|
+
end
|
186
|
+
end
|
121
187
|
|
122
|
-
|
188
|
+
describe "pretty URLs" do
|
123
189
|
|
190
|
+
before(:all) do
|
191
|
+
ActionController::Routing::Routes.draw do |map|
|
192
|
+
map.connect "articles/:year/:month/:day", :controller => 'articles', :action => 'find_by_date', :requirements => { :year => /\d{4}/, :month => /\d{1,2}/, :day => /\d{1,2}/ }
|
124
193
|
end
|
194
|
+
end
|
125
195
|
|
126
|
-
|
127
|
-
|
196
|
+
it "should work" do
|
197
|
+
response = http_options_request("/articles/2010/07/23")
|
198
|
+
assert response.kind_of?(Array)
|
199
|
+
assert response[0].should be 204
|
200
|
+
end
|
201
|
+
|
202
|
+
after(:all) do
|
203
|
+
ActionController::Routing::Routes.reload!
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "regular expressions and parameters" do
|
209
|
+
|
210
|
+
before(:all) do
|
211
|
+
ActionController::Routing::Routes.draw do |map|
|
212
|
+
map.geocode 'geocode/:postalcode', :controller => 'geocode', :action => 'show', :requirements => { :postalcode => /\d{5}(-\d{4})?/ }
|
128
213
|
end
|
214
|
+
end
|
129
215
|
|
216
|
+
it "should work" do
|
217
|
+
response = http_options_request("/geocode/20100")
|
218
|
+
assert response.kind_of?(Array)
|
219
|
+
assert response[0].should be 204
|
220
|
+
assert allows?(response[1], "GET")
|
130
221
|
end
|
131
222
|
|
132
|
-
|
223
|
+
after(:all) do
|
224
|
+
ActionController::Routing::Routes.reload!
|
225
|
+
end
|
226
|
+
end
|
133
227
|
|
134
|
-
|
135
|
-
|
136
|
-
|
228
|
+
describe "resource route within a namespace" do
|
229
|
+
|
230
|
+
before(:all) do
|
231
|
+
ActionController::Routing::Routes.draw do |map|
|
232
|
+
map.namespace :admin do |admin|
|
233
|
+
# Directs /admin/posts/* to Admin::PostsController (app/controllers/admin/posts_controller.rb)
|
234
|
+
admin.resources :posts
|
137
235
|
end
|
138
236
|
end
|
237
|
+
end
|
238
|
+
|
239
|
+
it "must understand an namespaced path" do
|
240
|
+
response = http_options_request("/admin/posts")
|
241
|
+
assert response.kind_of?(Array)
|
242
|
+
assert response[0].should be 204
|
243
|
+
assert allows?(response[1], "GET")
|
244
|
+
assert allows?(response[1], "POST")
|
245
|
+
end
|
139
246
|
|
140
|
-
|
141
|
-
|
247
|
+
after(:all) do
|
248
|
+
ActionController::Routing::Routes.reload!
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "deal the catch all" do
|
254
|
+
|
255
|
+
before(:all) do
|
256
|
+
ActionController::Routing::Routes.draw do |map|
|
257
|
+
map.resources :posts
|
258
|
+
map.connect ':controller/:action/:id'
|
142
259
|
end
|
260
|
+
end
|
143
261
|
|
262
|
+
it "must cheat :P" do
|
263
|
+
response = http_options_request("/posts")
|
264
|
+
assert response.kind_of?(Array)
|
265
|
+
assert response[0].should be 204
|
266
|
+
assert allows?(response[1], "GET")
|
267
|
+
assert allows?(response[1], "POST")
|
268
|
+
end
|
144
269
|
|
270
|
+
after(:all) do
|
271
|
+
ActionController::Routing::Routes.reload!
|
272
|
+
end
|
145
273
|
|
274
|
+
end
|
275
|
+
|
276
|
+
describe "another sample of named route" do
|
277
|
+
before(:all) do
|
278
|
+
ActionController::Routing::Routes.draw do |map|
|
279
|
+
map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
|
280
|
+
end
|
146
281
|
end
|
147
282
|
|
148
|
-
|
283
|
+
it "should work" do
|
284
|
+
response = http_options_request("/products/123/purchase")
|
285
|
+
assert response.kind_of?(Array)
|
286
|
+
assert response[0].should be 204
|
287
|
+
assert allows?(response[1], "ANY")
|
288
|
+
end
|
149
289
|
|
290
|
+
after(:all) do
|
291
|
+
ActionController::Routing::Routes.reload!
|
150
292
|
end
|
151
293
|
|
152
|
-
|
294
|
+
end
|
295
|
+
|
296
|
+
describe "Sample resource route with options" do
|
153
297
|
|
298
|
+
before(:all) do
|
299
|
+
ActionController::Routing::Routes.draw do |map|
|
300
|
+
map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
|
301
|
+
end
|
154
302
|
end
|
155
303
|
|
156
|
-
|
304
|
+
it "should work" do
|
305
|
+
response = http_options_request("/products/123/toggle")
|
306
|
+
assert response.kind_of?(Array)
|
307
|
+
assert response[0].should be 204
|
308
|
+
assert allows?(response[1], "POST")
|
157
309
|
end
|
158
310
|
|
159
|
-
|
311
|
+
it "should work" do
|
312
|
+
response = http_options_request("/products/123/short")
|
313
|
+
assert response.kind_of?(Array)
|
314
|
+
assert response[0].should be 204
|
315
|
+
assert allows?(response[1], "GET")
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should work" do
|
319
|
+
response = http_options_request("/products/sold")
|
320
|
+
assert response.kind_of?(Array)
|
321
|
+
assert response[0].should be 204
|
322
|
+
assert allows?(response[1], "GET")
|
323
|
+
end
|
324
|
+
|
325
|
+
after(:all) do
|
326
|
+
ActionController::Routing::Routes.reload!
|
160
327
|
end
|
161
328
|
|
162
329
|
end
|
@@ -166,4 +333,3 @@ describe Baurets::Optionsful::Server do
|
|
166
333
|
end
|
167
334
|
|
168
335
|
|
169
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', 'lib', "baurets", 'optionsful', "config.rb")
|
2
2
|
require File.join(File.dirname(__FILE__), '..', 'lib', "baurets", 'optionsful', "server.rb")
|
3
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', "baurets", 'optionsful', "documentator.rb")
|
4
3
|
require File.join(File.dirname(__FILE__), '..', 'lib', "baurets", 'optionsful', "introspections.rb")
|
5
4
|
# TODO ^ this was ugly?! :-S
|
6
5
|
|
@@ -15,7 +14,11 @@ require 'spec/interop/test'
|
|
15
14
|
require 'action_controller'
|
16
15
|
|
17
16
|
|
18
|
-
# set test environment
|
17
|
+
# set test environment
|
18
|
+
set :environment, :test
|
19
|
+
set :run, false
|
20
|
+
set :raise_errors, true
|
21
|
+
set :logging, true
|
19
22
|
|
20
23
|
DEFAULT_ENV = { "rack.version" => Rack::VERSION, "rack.input" => StringIO.new, "rack.errors" => StringIO.new,
|
21
24
|
"rack.multithread" => true, "rack.multiprocess" => true, "rack.run_once" => false, }
|
@@ -51,18 +54,6 @@ DEFAULT_ENV = { "rack.version" => Rack::VERSION, "rack.input" => StringIO.new, "
|
|
51
54
|
end
|
52
55
|
}
|
53
56
|
end
|
54
|
-
|
55
|
-
def fake_docs_app
|
56
|
-
app = Rack::Builder.new {
|
57
|
-
use Rack::CommonLogger
|
58
|
-
use Rack::ShowExceptions
|
59
|
-
use Baurets::Optionsful::Documentator
|
60
|
-
map "/lobster" do
|
61
|
-
use Rack::Lint
|
62
|
-
run Rack::Lobster.new
|
63
|
-
end
|
64
|
-
}
|
65
|
-
end
|
66
57
|
|
67
58
|
def mock_env(options = {})
|
68
59
|
FAKE_ENV.merge!(options)
|
@@ -72,16 +63,10 @@ DEFAULT_ENV = { "rack.version" => Rack::VERSION, "rack.input" => StringIO.new, "
|
|
72
63
|
complex_env = mock_env({"REQUEST_METHOD" => "OPTIONS", "PATH_INFO" => path })
|
73
64
|
response = Baurets::Optionsful::Server.new(app).call(complex_env)
|
74
65
|
end
|
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
|
-
|
66
|
+
|
82
67
|
def allows?(headers, method)
|
83
68
|
headers["Allow"].include?(method)
|
84
69
|
end
|
85
|
-
|
70
|
+
|
86
71
|
|
87
72
|
|
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: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marco Antonio Gonzalez Junior
|
@@ -15,26 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-31 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
22
|
-
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 51
|
30
|
-
segments:
|
31
|
-
- 4
|
32
|
-
- 2
|
33
|
-
- 2
|
34
|
-
version: 4.2.2
|
35
|
-
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
|
-
description: Optionsful provide dynamic information and HTTP's OPTION method support.
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Help building RESTful web services enabling HTTP OPTIONS verb on Ruby on Rails applications.
|
38
23
|
email: kayaman@baurets.net
|
39
24
|
executables: []
|
40
25
|
|
@@ -47,22 +32,16 @@ files:
|
|
47
32
|
- MIT-LICENSE
|
48
33
|
- Rakefile
|
49
34
|
- lib/optionsful.rb
|
50
|
-
- lib/baurets/optionsful/documentator.rb
|
51
35
|
- lib/baurets/optionsful/server.rb
|
52
36
|
- lib/baurets/optionsful/introspections.rb
|
53
37
|
- lib/baurets/optionsful/config.rb
|
54
38
|
- lib/baurets/optionsful/version.rb
|
55
39
|
- lib/tasks/optionsful.rake
|
56
40
|
- rails/init.rb
|
41
|
+
- samples/optionsful.yml
|
57
42
|
- spec/fixtures/optionsful.yml
|
58
43
|
- 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
44
|
- spec/optionsful_server_spec.rb
|
65
|
-
- spec/optionsful_documentator_spec.rb
|
66
45
|
- spec/optionsful_config_spec.rb
|
67
46
|
- spec/spec.opts
|
68
47
|
- spec/spec_helper.rb
|
@@ -99,6 +78,6 @@ rubyforge_project:
|
|
99
78
|
rubygems_version: 1.3.7
|
100
79
|
signing_key:
|
101
80
|
specification_version: 3
|
102
|
-
summary:
|
81
|
+
summary: Support HTTP OPTIONS verb on your Rails app.
|
103
82
|
test_files: []
|
104
83
|
|
@@ -1,158 +0,0 @@
|
|
1
|
-
module Baurets
|
2
|
-
module Optionsful
|
3
|
-
class Documentator
|
4
|
-
|
5
|
-
def initialize(app)
|
6
|
-
@app = app
|
7
|
-
@config = Baurets::Optionsful::Config.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(env)
|
11
|
-
unless env["PATH_INFO"].index(@config.base_path) == 0
|
12
|
-
response = @app.call(env)
|
13
|
-
else
|
14
|
-
response = extract_documentation(env)
|
15
|
-
end
|
16
|
-
response
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
require 'rubygems'
|
22
|
-
require 'yaml'
|
23
|
-
require 'RedCloth'
|
24
|
-
|
25
|
-
def verify_path(env)
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
def extract_documentation(env)
|
30
|
-
path = env["PATH_INFO"]
|
31
|
-
path = path.gsub(@config.base_path, '')
|
32
|
-
# do routing introspection:
|
33
|
-
routes = ::Baurets::Optionsful::Introspections.do_routing_introspection
|
34
|
-
# do request path investigation
|
35
|
-
route_guess = ::Baurets::Optionsful::Introspections.guess_route(routes,path)
|
36
|
-
# do the matches:
|
37
|
-
allow = ::Baurets::Optionsful::Introspections.do_the_matches(routes, route_guess)
|
38
|
-
http_methods = allow.split(", ")
|
39
|
-
|
40
|
-
path_parts = ::Baurets::Optionsful::Introspections.prepare_request_path(path)
|
41
|
-
|
42
|
-
controller_actions = []
|
43
|
-
http_methods.each do |verb|
|
44
|
-
controller_actions << [verb, relate_action_to_method(path_parts, verb)]
|
45
|
-
end
|
46
|
-
controller_actions.delete_if {|pair| pair[1].empty? }
|
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, {}, " "]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def build_html(srvc, methods)
|
65
|
-
html = "<html><head></head><body>"
|
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
|
88
|
-
end
|
89
|
-
html += "</body></html>"
|
90
|
-
html
|
91
|
-
end
|
92
|
-
|
93
|
-
def relate_action_to_method(path, verb)
|
94
|
-
action = ""
|
95
|
-
routes = ::Baurets::Optionsful::Introspections.do_routing_introspection
|
96
|
-
route_guess = ::Baurets::Optionsful::Introspections.guess_route(routes, path)
|
97
|
-
routes.each do |route|
|
98
|
-
if ((route.first == route_guess) && (route[1][0] == verb))
|
99
|
-
action = route[1][1] unless route[1][1].empty?
|
100
|
-
end
|
101
|
-
end
|
102
|
-
action
|
103
|
-
end
|
104
|
-
|
105
|
-
def file_lines(file_name)
|
106
|
-
lines = []
|
107
|
-
begin
|
108
|
-
file = File.new(file_name, "r")
|
109
|
-
while (line = file.gets)
|
110
|
-
line = line.strip
|
111
|
-
lines << line unless line.empty?
|
112
|
-
end
|
113
|
-
file.close
|
114
|
-
rescue => err
|
115
|
-
puts "Exception: #{err}"
|
116
|
-
err
|
117
|
-
end
|
118
|
-
lines.delete(nil)
|
119
|
-
lines
|
120
|
-
end
|
121
|
-
|
122
|
-
def extract_comments_above(file_name, line_number)
|
123
|
-
lines = file_lines(file_name)
|
124
|
-
doc = []
|
125
|
-
line_number = line_number -1
|
126
|
-
while ((line_number = line_number -1) && (line_number >= 0) && (!lines.nil?) && (!lines[line_number].empty?))
|
127
|
-
line = lines[line_number].lstrip
|
128
|
-
if line[0] == 35
|
129
|
-
doc << line
|
130
|
-
else
|
131
|
-
line_number = 0
|
132
|
-
end
|
133
|
-
end
|
134
|
-
doc = doc.reverse
|
135
|
-
doc
|
136
|
-
end
|
137
|
-
|
138
|
-
def find_line_for(file, name, type)
|
139
|
-
lines = file_lines(file)
|
140
|
-
signature = ""
|
141
|
-
if type == :class
|
142
|
-
signature = "class " + name
|
143
|
-
elsif type == :method
|
144
|
-
signature = "def " + name
|
145
|
-
end
|
146
|
-
counter = 1;
|
147
|
-
lines.each do |line|
|
148
|
-
if line.include? signature
|
149
|
-
return counter
|
150
|
-
end
|
151
|
-
counter += 1
|
152
|
-
end
|
153
|
-
counter = 0
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
end
|