cuba 0.3.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.markdown +78 -37
- data/cuba.gemspec +2 -2
- data/lib/cuba/ron.rb +294 -5
- data/lib/cuba/version.rb +1 -1
- data/test/accept.rb +16 -0
- data/test/captures.rb +127 -0
- data/test/extension.rb +21 -0
- data/test/helper.rb +5 -0
- data/test/integration.rb +1 -4
- data/test/number.rb +36 -0
- data/test/on.rb +91 -0
- data/test/path.rb +73 -0
- data/test/run.rb +23 -0
- data/test/segment.rb +45 -0
- metadata +13 -26
- data/lib/cuba/rum.rb +0 -157
- data/test/webrat.log +0 -5
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2010 Michel Martens and
|
1
|
+
Copyright (c) 2010 Michel Martens, Damian Janowski and Cyril David
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.markdown
CHANGED
@@ -8,13 +8,17 @@ Rum based microframework for web development.
|
|
8
8
|
Description
|
9
9
|
-----------
|
10
10
|
|
11
|
-
Cuba is a
|
12
|
-
a tiny but powerful mapper for [Rack]
|
13
|
-
applications.
|
11
|
+
Cuba is a microframework for web development heavily inspired by [Rum][rum],
|
12
|
+
a tiny but powerful mapper for [Rack][rack] applications.
|
14
13
|
|
15
|
-
It integrates many templates via [Tilt]
|
16
|
-
|
17
|
-
|
14
|
+
It integrates many templates via [Tilt][tilt], and testing via
|
15
|
+
[Cutest][cutest] and [Capybara][capybara].
|
16
|
+
|
17
|
+
[rum]: http://github.com/chneukirchen/rum
|
18
|
+
[rack]: http://github.com/chneukirchen/rack
|
19
|
+
[tilt]: http://github.com/rtomayko/tilt
|
20
|
+
[cutest]: http://github.com/djanowski/cutest
|
21
|
+
[capybara]: http://github.com/jnicklas/capybara
|
18
22
|
|
19
23
|
Usage
|
20
24
|
-----
|
@@ -32,7 +36,7 @@ Here's a simple application:
|
|
32
36
|
res.write "Hello world!"
|
33
37
|
end
|
34
38
|
|
35
|
-
on
|
39
|
+
on true do
|
36
40
|
res.redirect "/hello"
|
37
41
|
end
|
38
42
|
end
|
@@ -56,40 +60,77 @@ To run it, you can create a `config.ru`:
|
|
56
60
|
|
57
61
|
run Cuba
|
58
62
|
|
63
|
+
Here's an example showcasing how different matchers work:
|
64
|
+
|
65
|
+
require "cuba"
|
66
|
+
|
67
|
+
Cuba.use Rack::Session::Cookie
|
68
|
+
|
69
|
+
Cuba.define do
|
70
|
+
|
71
|
+
# /about
|
72
|
+
on path("about") do
|
73
|
+
res.write "About"
|
74
|
+
end
|
75
|
+
|
76
|
+
# /styles/basic.css
|
77
|
+
on path("styles"), extension("css") do |file|
|
78
|
+
res.write "Filename: #{file}" #=> "Filename: basic"
|
79
|
+
end
|
80
|
+
|
81
|
+
# /post/2011/02/16/hello
|
82
|
+
on path("post"), number, number, number, segment do |y, m, d, slug|
|
83
|
+
res.write "#{y}-#{m}-#{d} #{slug}" #=> "2011-02-16 hello"
|
84
|
+
end
|
85
|
+
|
86
|
+
# /username/foobar
|
87
|
+
on path("username"), segment do |username|
|
88
|
+
|
89
|
+
user = User.find_by_username(username) # username == "foobar"
|
90
|
+
|
91
|
+
# /username/foobar/posts
|
92
|
+
on path("posts") do
|
93
|
+
|
94
|
+
# You can access `user` here, because the `on` blocks
|
95
|
+
# are closures.
|
96
|
+
res.write "Total Posts: #{user.posts.size}" #=> "Total Posts: 6"
|
97
|
+
end
|
98
|
+
|
99
|
+
# /username/foobar/following
|
100
|
+
on path("following") do
|
101
|
+
res.write user.following.size #=> "1301"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# /search?q=barbaz
|
106
|
+
on path("search"), param("q") do |query|
|
107
|
+
res.write "Searched for #{query}" #=> "Searched for barbaz"
|
108
|
+
end
|
109
|
+
|
110
|
+
on post
|
111
|
+
on path("login")
|
112
|
+
|
113
|
+
# POST /login, user: foo, pass: baz
|
114
|
+
on param("user"), param("pass") do |user, pass|
|
115
|
+
res.write "#{user}:#{pass}" #=> "foo:baz"
|
116
|
+
end
|
117
|
+
|
118
|
+
# If the params `user` and `pass` are not provided, this block will
|
119
|
+
# get executed.
|
120
|
+
on true do
|
121
|
+
res.write "You need to provide user and pass!"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
59
128
|
That's it, you can now run `rackup` and enjoy what you have just created.
|
60
129
|
|
61
|
-
|
62
|
-
|
63
|
-
check the documentation for [Cutest](http://github.com/djanowski/cutest) and
|
64
|
-
[Capybara](http://github.com/jnicklas/capybara).
|
130
|
+
To read more about testing, check the documentation for [Cutest][cutest] and
|
131
|
+
[Capybara][capybara].
|
65
132
|
|
66
133
|
Installation
|
67
134
|
------------
|
68
135
|
|
69
136
|
$ gem install cuba
|
70
|
-
|
71
|
-
License
|
72
|
-
-------
|
73
|
-
|
74
|
-
Copyright (c) 2010 Michel Martens and Damian Janowski
|
75
|
-
|
76
|
-
Permission is hereby granted, free of charge, to any person
|
77
|
-
obtaining a copy of this software and associated documentation
|
78
|
-
files (the "Software"), to deal in the Software without
|
79
|
-
restriction, including without limitation the rights to use,
|
80
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
81
|
-
copies of the Software, and to permit persons to whom the
|
82
|
-
Software is furnished to do so, subject to the following
|
83
|
-
conditions:
|
84
|
-
|
85
|
-
The above copyright notice and this permission notice shall be
|
86
|
-
included in all copies or substantial portions of the Software.
|
87
|
-
|
88
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
89
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
90
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
91
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
92
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
93
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
94
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
95
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
data/cuba.gemspec
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "cuba"
|
3
|
-
s.version = "0.
|
3
|
+
s.version = "1.0.0"
|
4
4
|
s.summary = "Rum based microframework for web applications."
|
5
5
|
s.description = "Cuba is a light wrapper for Rum, a microframework for Rack applications."
|
6
6
|
s.authors = ["Michel Martens"]
|
7
7
|
s.email = ["michel@soveran.com"]
|
8
8
|
s.homepage = "http://github.com/soveran/cuba"
|
9
|
-
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/cuba/ron.rb", "lib/cuba/
|
9
|
+
s.files = ["LICENSE", "README.markdown", "Rakefile", "lib/cuba/ron.rb", "lib/cuba/test.rb", "lib/cuba/version.rb", "lib/cuba.rb", "cuba.gemspec", "test/accept.rb", "test/captures.rb", "test/extension.rb", "test/helper.rb", "test/integration.rb", "test/number.rb", "test/on.rb", "test/path.rb", "test/run.rb", "test/segment.rb"]
|
10
10
|
s.add_dependency "rack", "~> 1.2"
|
11
11
|
s.add_dependency "tilt", "~> 1.1"
|
12
12
|
s.add_development_dependency "cutest", "~> 0.1"
|
data/lib/cuba/ron.rb
CHANGED
@@ -1,20 +1,309 @@
|
|
1
|
-
require "
|
1
|
+
require "rack"
|
2
2
|
require "tilt"
|
3
3
|
|
4
|
+
class Rack::Response
|
5
|
+
# 301 Moved Permanently
|
6
|
+
# 302 Found
|
7
|
+
# 303 See Other
|
8
|
+
# 307 Temporary Redirect
|
9
|
+
def redirect(target, status = 302)
|
10
|
+
self.status = status
|
11
|
+
self["Location"] = target
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Based on Rum: http://github.com/chneukirchen/rum
|
16
|
+
#
|
17
|
+
# Summary of changes
|
18
|
+
#
|
19
|
+
# 1. Only relevant captures are yielded.
|
20
|
+
# 2. The #extension matcher is used more like #path.
|
21
|
+
# 3. Miscellaneous coding style changes.
|
22
|
+
#
|
4
23
|
module Cuba
|
5
|
-
class Ron
|
24
|
+
class Ron
|
25
|
+
attr :env
|
26
|
+
attr :req
|
27
|
+
attr :res
|
28
|
+
attr :captures
|
29
|
+
|
30
|
+
def initialize(&blk)
|
31
|
+
@blk = blk
|
32
|
+
@captures = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(env)
|
36
|
+
dup._call(env)
|
37
|
+
end
|
38
|
+
|
39
|
+
def _call(env)
|
40
|
+
@env = env
|
41
|
+
@req = Rack::Request.new(env)
|
42
|
+
@res = Rack::Response.new
|
43
|
+
@matched = false
|
44
|
+
|
45
|
+
catch(:rum_run_next_app) do
|
46
|
+
instance_eval(&@blk)
|
47
|
+
|
48
|
+
@res.status = 404 unless @matched || !@res.empty?
|
49
|
+
|
50
|
+
return @res.finish
|
51
|
+
end.call(env)
|
52
|
+
end
|
53
|
+
|
54
|
+
# @private Used internally by #render to cache the
|
55
|
+
# Tilt templates.
|
6
56
|
def _cache
|
7
57
|
Thread.current[:_cache] ||= Tilt::Cache.new
|
8
58
|
end
|
59
|
+
private :_cache
|
9
60
|
|
10
|
-
|
61
|
+
# Render any type of template file supported by Tilt.
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
#
|
65
|
+
# # Renders home, and is assumed to be HAML.
|
66
|
+
# render("home.haml")
|
67
|
+
#
|
68
|
+
# # Renders with some local variables
|
69
|
+
# render("home.haml", site_name: "My Site")
|
70
|
+
#
|
71
|
+
# # Renders with HAML options
|
72
|
+
# render("home.haml", {}, ugly: true, format: :html5)
|
73
|
+
#
|
74
|
+
def render(template, locals = {}, options = {})
|
11
75
|
_cache.fetch(template, locals) {
|
12
|
-
Tilt.new(template)
|
76
|
+
Tilt.new(template, 1, options)
|
13
77
|
}.render(self, locals)
|
14
78
|
end
|
15
79
|
|
80
|
+
# Basic wrapper for using Rack session.
|
16
81
|
def session
|
17
82
|
@session ||= env['rack.session']
|
18
83
|
end
|
84
|
+
|
85
|
+
# The heart of the path / verb / any condition matching.
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
#
|
89
|
+
# on get do
|
90
|
+
# res.write "GET"
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# on get, path("signup") do
|
94
|
+
# res.write "Signup
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# on path("user"), segment do |uid|
|
98
|
+
# res.write "User: #{uid}"
|
99
|
+
# end
|
100
|
+
#
|
101
|
+
# on path("styles"), extension("css") do |file|
|
102
|
+
# res.write render("styles/#{file}.sass")
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
def on(*args, &block)
|
106
|
+
# No use running any other matchers if we've already found a
|
107
|
+
# proper matcher.
|
108
|
+
return if @matched
|
109
|
+
|
110
|
+
try do
|
111
|
+
# For every block, we make sure to reset captures so that
|
112
|
+
# nesting matchers won't mess with each other's captures.
|
113
|
+
@captures = []
|
114
|
+
|
115
|
+
# We stop evaluation of this entire matcher unless
|
116
|
+
# each and every `arg` defined for this matcher evaluates
|
117
|
+
# to a non-false value.
|
118
|
+
#
|
119
|
+
# Short circuit examples:
|
120
|
+
# on true, false do
|
121
|
+
#
|
122
|
+
# # PATH_INFO=/user
|
123
|
+
# on true, path("signup")
|
124
|
+
args.each do |arg|
|
125
|
+
return unless arg == true || arg != false && arg.call
|
126
|
+
end
|
127
|
+
|
128
|
+
# The captures we yield here were generated and assembled
|
129
|
+
# by evaluating each of the `arg`s above. Most of these
|
130
|
+
# are carried out by #path.
|
131
|
+
yield *captures
|
132
|
+
|
133
|
+
# At this point, we've successfully matched with some corresponding
|
134
|
+
# matcher, so we can skip all other matchers defined.
|
135
|
+
@matched = true
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# @private Used internally by #on to ensure that SCRIPT_NAME and
|
140
|
+
# PATH_INFO are reset to their proper values.
|
141
|
+
def try
|
142
|
+
script, path = env["SCRIPT_NAME"], env["PATH_INFO"]
|
143
|
+
|
144
|
+
yield
|
145
|
+
|
146
|
+
env["SCRIPT_NAME"], env["PATH_INFO"] = script, path
|
147
|
+
|
148
|
+
ensure
|
149
|
+
unless @matched
|
150
|
+
env["SCRIPT_NAME"], env["PATH_INFO"] = script, path
|
151
|
+
end
|
152
|
+
end
|
153
|
+
private :try
|
154
|
+
|
155
|
+
# Probably the most useful helper for writing matchers.
|
156
|
+
#
|
157
|
+
# @example
|
158
|
+
# # matches PATH_INFO=/signup
|
159
|
+
# on path("signup") do
|
160
|
+
#
|
161
|
+
# # matches PATH_INFO=/user123
|
162
|
+
# on path("user(\\d+)") do |uid|
|
163
|
+
#
|
164
|
+
# # matches PATH_INFO=/user/1
|
165
|
+
# on path("user"), path("(\\d+)") do |uid|
|
166
|
+
#
|
167
|
+
# In fact, the other matchers (#segment, #number, #extension)
|
168
|
+
# ride on this method.
|
169
|
+
def path(pattern)
|
170
|
+
lambda { consume(pattern) }
|
171
|
+
end
|
172
|
+
|
173
|
+
# @private Used by #path to adjust the `PATH_INFO` and `SCRIPT_NAME`.
|
174
|
+
# This is done so that nesting of matchers would work.
|
175
|
+
#
|
176
|
+
# @example
|
177
|
+
# # PATH_INFO=/doctors/account
|
178
|
+
# on path("doctors") do
|
179
|
+
# # PATH_INFO = /account
|
180
|
+
# on path("account") do
|
181
|
+
# res.write "Settings page"
|
182
|
+
# end
|
183
|
+
# end
|
184
|
+
def consume(pattern)
|
185
|
+
return unless match = env["PATH_INFO"].match(/\A\/(#{pattern})(?:\/|\z)/)
|
186
|
+
|
187
|
+
path, *vars = match.captures
|
188
|
+
|
189
|
+
env["SCRIPT_NAME"] += "/#{path}"
|
190
|
+
env["PATH_INFO"] = "/#{match.post_match}"
|
191
|
+
|
192
|
+
captures.push(*vars)
|
193
|
+
end
|
194
|
+
private :consume
|
195
|
+
|
196
|
+
# A matcher for numeric ids.
|
197
|
+
#
|
198
|
+
# @example
|
199
|
+
# on path("user"), number do |uid|
|
200
|
+
# res.write "User: #{uid}"
|
201
|
+
# end
|
202
|
+
def number
|
203
|
+
path("(\\d+)")
|
204
|
+
end
|
205
|
+
|
206
|
+
# A matcher for anything without slashes. Useful for mapping to slugs.
|
207
|
+
#
|
208
|
+
# @example
|
209
|
+
# on path("article"), segment do |slug|
|
210
|
+
# Article.find_by_slug(slug)
|
211
|
+
#
|
212
|
+
# end
|
213
|
+
def segment
|
214
|
+
path("([^\\/]+)")
|
215
|
+
end
|
216
|
+
|
217
|
+
# A matcher for files with a certain extension.
|
218
|
+
#
|
219
|
+
# @example
|
220
|
+
# # PATH_INFO=/style/app.css
|
221
|
+
# on path("style"), extension("css") do |file|
|
222
|
+
# res.write file # writes app
|
223
|
+
# end
|
224
|
+
def extension(ext = "\\w+")
|
225
|
+
path("([^\\/]+?)\.#{ext}\\z")
|
226
|
+
end
|
227
|
+
|
228
|
+
# Used to ensure that certain request parameters are present. Acts like a
|
229
|
+
# precondition / assertion for your route.
|
230
|
+
#
|
231
|
+
# @example
|
232
|
+
# # POST with data like user[fname]=John&user[lname]=Doe
|
233
|
+
# on path("signup"), param("user") do |atts|
|
234
|
+
# User.create(atts)
|
235
|
+
# end
|
236
|
+
def param(key, default = nil)
|
237
|
+
lambda { captures << (req[key] || default) }
|
238
|
+
end
|
239
|
+
|
240
|
+
def header(key, default = nil)
|
241
|
+
lambda { env[key.upcase.tr("-","_")] || default }
|
242
|
+
end
|
243
|
+
|
244
|
+
# Useful for matching against the request host (i.e. HTTP_HOST).
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# on host("account1.example.com"), path("api") do
|
248
|
+
# res.write "You have reached the API of account1."
|
249
|
+
# end
|
250
|
+
def host(hostname)
|
251
|
+
req.host == hostname
|
252
|
+
end
|
253
|
+
|
254
|
+
# If you want to match against the HTTP_ACCEPT value.
|
255
|
+
#
|
256
|
+
# @example
|
257
|
+
# # HTTP_ACCEPT=application/xml
|
258
|
+
# on accept("application/xml") do
|
259
|
+
# # automatically set to application/xml.
|
260
|
+
# res.write res["Content-Type"]
|
261
|
+
# end
|
262
|
+
def accept(mimetype)
|
263
|
+
lambda do
|
264
|
+
env["HTTP_ACCEPT"].split(",").any? { |s| s.strip == mimetype } and
|
265
|
+
res["Content-Type"] = mimetype
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Syntactic sugar for providing catch-all matches.
|
270
|
+
#
|
271
|
+
# @example
|
272
|
+
# on default do
|
273
|
+
# res.write "404"
|
274
|
+
# end
|
275
|
+
def default
|
276
|
+
true
|
277
|
+
end
|
278
|
+
|
279
|
+
# Syntatic sugar for providing HTTP Verb matching.
|
280
|
+
#
|
281
|
+
# @example
|
282
|
+
# on get, path("signup") do
|
283
|
+
# end
|
284
|
+
#
|
285
|
+
# on post, path("signup") do
|
286
|
+
# end
|
287
|
+
def get ; req.get? end
|
288
|
+
def post ; req.post? end
|
289
|
+
def put ; req.put? end
|
290
|
+
def delete ; req.delete? end
|
291
|
+
|
292
|
+
# If you want to halt the processing of an existing handler
|
293
|
+
# and continue it via a different handler.
|
294
|
+
#
|
295
|
+
# @example
|
296
|
+
# def redirect(*args)
|
297
|
+
# run Cuba::Ron.new { on(default) { res.redirect(*args) }}
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# on path("account") do
|
301
|
+
# redirect "/login" unless session["uid"]
|
302
|
+
#
|
303
|
+
# res.write "Super secure account info."
|
304
|
+
# end
|
305
|
+
def run(app)
|
306
|
+
throw :rum_run_next_app, app
|
307
|
+
end
|
19
308
|
end
|
20
|
-
end
|
309
|
+
end
|
data/lib/cuba/version.rb
CHANGED
data/test/accept.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
test "accept mimetypes" do
|
4
|
+
Cuba.define do
|
5
|
+
on accept("application/xml") do
|
6
|
+
res.write res["Content-Type"]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
env = { "HTTP_ACCEPT" => "application/xml",
|
11
|
+
"SCRIPT_NAME" => "/", "PATH_INFO" => "/post" }
|
12
|
+
|
13
|
+
_, _, resp = Cuba.call(env)
|
14
|
+
|
15
|
+
assert_equal ["application/xml"], resp.body
|
16
|
+
end
|
data/test/captures.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
require "stringio"
|
3
|
+
|
4
|
+
test "doesn't yield HOST" do
|
5
|
+
Cuba.define do
|
6
|
+
on host("example.com") do |*args|
|
7
|
+
res.write args.size
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
env = { "HTTP_HOST" => "example.com" }
|
12
|
+
|
13
|
+
_, _, resp = Cuba.call(env)
|
14
|
+
|
15
|
+
assert_equal ["0"], resp.body
|
16
|
+
end
|
17
|
+
|
18
|
+
test "doesn't yield the verb" do
|
19
|
+
Cuba.define do
|
20
|
+
on get do |*args|
|
21
|
+
res.write args.size
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
env = { "REQUEST_METHOD" => "GET" }
|
26
|
+
|
27
|
+
_, _, resp = Cuba.call(env)
|
28
|
+
|
29
|
+
assert_equal ["0"], resp.body
|
30
|
+
end
|
31
|
+
|
32
|
+
test "doesn't yield the path" do
|
33
|
+
Cuba.define do
|
34
|
+
on get, path("home") do |*args|
|
35
|
+
res.write args.size
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/home",
|
40
|
+
"SCRIPT_NAME" => "/" }
|
41
|
+
|
42
|
+
_, _, resp = Cuba.call(env)
|
43
|
+
|
44
|
+
assert_equal ["0"], resp.body
|
45
|
+
end
|
46
|
+
|
47
|
+
test "yields the segment" do
|
48
|
+
Cuba.define do
|
49
|
+
on get, path("user"), segment do |id|
|
50
|
+
res.write id
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/user/johndoe",
|
55
|
+
"SCRIPT_NAME" => "/" }
|
56
|
+
|
57
|
+
_, _, resp = Cuba.call(env)
|
58
|
+
|
59
|
+
assert_equal ["johndoe"], resp.body
|
60
|
+
end
|
61
|
+
|
62
|
+
test "yields a number" do
|
63
|
+
Cuba.define do
|
64
|
+
on get, path("user"), number do |id|
|
65
|
+
res.write id
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/user/101",
|
70
|
+
"SCRIPT_NAME" => "/" }
|
71
|
+
|
72
|
+
_, _, resp = Cuba.call(env)
|
73
|
+
|
74
|
+
assert_equal ["101"], resp.body
|
75
|
+
end
|
76
|
+
|
77
|
+
test "yields an extension" do
|
78
|
+
Cuba.define do
|
79
|
+
on get, path("css"), extension("css") do |file|
|
80
|
+
res.write file
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/css/app.css",
|
85
|
+
"SCRIPT_NAME" => "/" }
|
86
|
+
|
87
|
+
_, _, resp = Cuba.call(env)
|
88
|
+
|
89
|
+
assert_equal ["app"], resp.body
|
90
|
+
end
|
91
|
+
|
92
|
+
test "yields a param" do
|
93
|
+
Cuba.define do
|
94
|
+
on get, path("signup"), param("email") do |email|
|
95
|
+
res.write email
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/signup",
|
100
|
+
"SCRIPT_NAME" => "/", "rack.input" => StringIO.new,
|
101
|
+
"QUERY_STRING" => "email=john@doe.com" }
|
102
|
+
|
103
|
+
_, _, resp = Cuba.call(env)
|
104
|
+
|
105
|
+
assert_equal ["john@doe.com"], resp.body
|
106
|
+
end
|
107
|
+
|
108
|
+
test "yields a segment per nested block" do
|
109
|
+
Cuba.define do
|
110
|
+
on segment do |one|
|
111
|
+
on segment do |two|
|
112
|
+
on segment do |three|
|
113
|
+
res.write one
|
114
|
+
res.write two
|
115
|
+
res.write three
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
env = { "REQUEST_METHOD" => "GET", "PATH_INFO" => "/one/two/three",
|
122
|
+
"SCRIPT_NAME" => "/" }
|
123
|
+
|
124
|
+
_, _, resp = Cuba.call(env)
|
125
|
+
|
126
|
+
assert_equal ["one", "two", "three"], resp.body
|
127
|
+
end
|
data/test/extension.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
setup do
|
4
|
+
Cuba.define do
|
5
|
+
on path("styles") do
|
6
|
+
on extension("css") do |file|
|
7
|
+
res.write file
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
{ "SCRIPT_NAME" => "/", "PATH_INFO" => "/styles" }
|
13
|
+
end
|
14
|
+
|
15
|
+
test "/styles/reset.css" do |env|
|
16
|
+
env["PATH_INFO"] += "/reset.css"
|
17
|
+
|
18
|
+
_, _, resp = Cuba.call(env)
|
19
|
+
|
20
|
+
assert_equal ["reset"], resp.body
|
21
|
+
end
|
data/test/helper.rb
ADDED
data/test/integration.rb
CHANGED
data/test/number.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
setup do
|
4
|
+
{ "SCRIPT_NAME" => "/", "PATH_INFO" => "/about/1/2" }
|
5
|
+
end
|
6
|
+
|
7
|
+
test "paths and numbers" do |env|
|
8
|
+
Cuba.define do
|
9
|
+
on path("about") do
|
10
|
+
on number, number do |one, two|
|
11
|
+
res.write one
|
12
|
+
res.write two
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
_, _, resp = Cuba.call(env)
|
18
|
+
|
19
|
+
assert_equal ["1", "2"], resp.body
|
20
|
+
end
|
21
|
+
|
22
|
+
test "paths and decimals" do |env|
|
23
|
+
Cuba.define do
|
24
|
+
on path("about") do
|
25
|
+
on number do |one|
|
26
|
+
res.write one
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
env["PATH_INFO"] = "/about/1.2"
|
32
|
+
|
33
|
+
_, _, resp = Cuba.call(env)
|
34
|
+
|
35
|
+
assert_equal [], resp.body
|
36
|
+
end
|
data/test/on.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
test "executes on true" do
|
4
|
+
Cuba.define do
|
5
|
+
on true do
|
6
|
+
res.write "+1"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
_, _, resp = Cuba.call({})
|
11
|
+
|
12
|
+
assert_equal ["+1"], resp.body
|
13
|
+
end
|
14
|
+
|
15
|
+
test "restores SCRIPT_NAME and PATH_INFO" do
|
16
|
+
Cuba.define do
|
17
|
+
on true do
|
18
|
+
env["SCRIPT_NAME"] = "foo"
|
19
|
+
env["PATH_INFO"] = "/hello"
|
20
|
+
|
21
|
+
raise "Something went wrong"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
env = { "SCRIPT_NAME" => "/", "PATH_INFO" => "/hello" }
|
26
|
+
|
27
|
+
begin
|
28
|
+
_, _, resp = Cuba.call(env)
|
29
|
+
rescue
|
30
|
+
end
|
31
|
+
|
32
|
+
assert_equal "/", env["SCRIPT_NAME"]
|
33
|
+
assert_equal "/hello", env["PATH_INFO"]
|
34
|
+
end
|
35
|
+
|
36
|
+
test "ensures SCRIPT_NAME and PATH_INFO are reverted" do
|
37
|
+
Cuba.define do
|
38
|
+
on lambda { env["SCRIPT_NAME"] = "/hello"; false } do
|
39
|
+
res.write "Unreachable"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
env = { "SCRIPT_NAME" => "/", "PATH_INFO" => "/hello" }
|
44
|
+
|
45
|
+
_, _, resp = Cuba.call(env)
|
46
|
+
|
47
|
+
assert_equal "/", env["SCRIPT_NAME"]
|
48
|
+
assert_equal "/hello", env["PATH_INFO"]
|
49
|
+
assert_equal [], resp.body
|
50
|
+
end
|
51
|
+
|
52
|
+
test "skips consecutive matches" do
|
53
|
+
Cuba.define do
|
54
|
+
on true do
|
55
|
+
env["foo"] = "foo"
|
56
|
+
|
57
|
+
res.write "foo"
|
58
|
+
end
|
59
|
+
|
60
|
+
on true do
|
61
|
+
env["bar"] = "bar"
|
62
|
+
|
63
|
+
res.write "bar"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
env = {}
|
68
|
+
|
69
|
+
_, _, resp = Cuba.call(env)
|
70
|
+
|
71
|
+
assert_equal "foo", env["foo"]
|
72
|
+
assert_equal ["foo"], resp.body
|
73
|
+
|
74
|
+
assert ! env["bar"]
|
75
|
+
end
|
76
|
+
|
77
|
+
test "finds first match available" do
|
78
|
+
Cuba.define do
|
79
|
+
on false do
|
80
|
+
res.write "foo"
|
81
|
+
end
|
82
|
+
|
83
|
+
on true do
|
84
|
+
res.write "bar"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
_, _, resp = Cuba.call({})
|
89
|
+
|
90
|
+
assert_equal ["bar"], resp.body
|
91
|
+
end
|
data/test/path.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
setup do
|
4
|
+
{ "SCRIPT_NAME" => "/", "PATH_INFO" => "/about" }
|
5
|
+
end
|
6
|
+
|
7
|
+
test "one level path" do |env|
|
8
|
+
Cuba.define do
|
9
|
+
on path("about") do
|
10
|
+
res.write "About"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
_, _, resp = Cuba.call(env)
|
15
|
+
|
16
|
+
assert_equal ["About"], resp.body
|
17
|
+
assert_equal({ "SCRIPT_NAME" => "/", "PATH_INFO" => "/about" }, env)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "two level nested paths" do |env|
|
21
|
+
Cuba.define do
|
22
|
+
on path("about") do
|
23
|
+
on path("1") do
|
24
|
+
res.write "+1"
|
25
|
+
end
|
26
|
+
|
27
|
+
on path("2") do
|
28
|
+
res.write "+2"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
env["PATH_INFO"] = "/about/1"
|
34
|
+
|
35
|
+
_, _, resp = Cuba.call(env)
|
36
|
+
|
37
|
+
assert_equal ["+1"], resp.body
|
38
|
+
|
39
|
+
env["PATH_INFO"] = "/about/2"
|
40
|
+
|
41
|
+
_, _, resp = Cuba.call(env)
|
42
|
+
|
43
|
+
assert_equal ["+2"], resp.body
|
44
|
+
end
|
45
|
+
|
46
|
+
test "two level inlined paths" do |env|
|
47
|
+
Cuba.define do
|
48
|
+
on path("a"), path("b") do
|
49
|
+
res.write "a"
|
50
|
+
res.write "b"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
env["PATH_INFO"] = "/a/b"
|
55
|
+
|
56
|
+
_, _, resp = Cuba.call(env)
|
57
|
+
|
58
|
+
assert_equal ["a", "b"], resp.body
|
59
|
+
end
|
60
|
+
|
61
|
+
test "a path with some regex captures" do |env|
|
62
|
+
Cuba.define do
|
63
|
+
on path("user(\\d+)") do |uid|
|
64
|
+
res.write uid
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
env["PATH_INFO"] = "/user123"
|
69
|
+
|
70
|
+
_, _, resp = Cuba.call(env)
|
71
|
+
|
72
|
+
assert_equal ["123"], resp.body
|
73
|
+
end
|
data/test/run.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
test "redirect canonical example" do
|
4
|
+
Cuba.define do
|
5
|
+
def redirect(*args)
|
6
|
+
run Cuba::Ron.new { on(true) { res.redirect(*args) }}
|
7
|
+
end
|
8
|
+
|
9
|
+
on path("account") do
|
10
|
+
redirect "/login", 307
|
11
|
+
|
12
|
+
res.write "Super secure content"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
env = { "SCRIPT_NAME" => "/", "PATH_INFO" => "/account" }
|
17
|
+
|
18
|
+
_, _, resp = Cuba.call(env)
|
19
|
+
|
20
|
+
assert_equal "/login", resp["Location"]
|
21
|
+
assert_equal 307, resp.status
|
22
|
+
assert_equal [], resp.body
|
23
|
+
end
|
data/test/segment.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
setup do
|
4
|
+
Cuba.define do
|
5
|
+
on path("post") do
|
6
|
+
on segment do |id|
|
7
|
+
res.write id
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
{ "SCRIPT_NAME" => "/", "PATH_INFO" => "/post" }
|
13
|
+
end
|
14
|
+
|
15
|
+
test "matches numeric ids" do |env|
|
16
|
+
env["PATH_INFO"] += "/1"
|
17
|
+
|
18
|
+
_, _, resp = Cuba.call(env)
|
19
|
+
|
20
|
+
assert_equal ["1"], resp.body
|
21
|
+
end
|
22
|
+
|
23
|
+
test "matches decimal numbers" do |env|
|
24
|
+
env["PATH_INFO"] += "/1.1"
|
25
|
+
|
26
|
+
_, _, resp = Cuba.call(env)
|
27
|
+
|
28
|
+
assert_equal ["1.1"], resp.body
|
29
|
+
end
|
30
|
+
|
31
|
+
test "matches slugs" do |env|
|
32
|
+
env["PATH_INFO"] += "/my-blog-post-about-cuba"
|
33
|
+
|
34
|
+
_, _, resp = Cuba.call(env)
|
35
|
+
|
36
|
+
assert_equal ["my-blog-post-about-cuba"], resp.body
|
37
|
+
end
|
38
|
+
|
39
|
+
test "matches only the first segment available" do |env|
|
40
|
+
env["PATH_INFO"] += "/one/two/three"
|
41
|
+
|
42
|
+
_, _, resp = Cuba.call(env)
|
43
|
+
|
44
|
+
assert_equal ["one"], resp.body
|
45
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
- 0
|
9
|
-
version: 0.3.0
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
10
6
|
platform: ruby
|
11
7
|
authors:
|
12
8
|
- Michel Martens
|
@@ -14,7 +10,7 @@ autorequire:
|
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
12
|
|
17
|
-
date:
|
13
|
+
date: 2011-02-16 00:00:00 -03:00
|
18
14
|
default_executable:
|
19
15
|
dependencies:
|
20
16
|
- !ruby/object:Gem::Dependency
|
@@ -25,9 +21,6 @@ dependencies:
|
|
25
21
|
requirements:
|
26
22
|
- - ~>
|
27
23
|
- !ruby/object:Gem::Version
|
28
|
-
segments:
|
29
|
-
- 1
|
30
|
-
- 2
|
31
24
|
version: "1.2"
|
32
25
|
type: :runtime
|
33
26
|
version_requirements: *id001
|
@@ -39,9 +32,6 @@ dependencies:
|
|
39
32
|
requirements:
|
40
33
|
- - ~>
|
41
34
|
- !ruby/object:Gem::Version
|
42
|
-
segments:
|
43
|
-
- 1
|
44
|
-
- 1
|
45
35
|
version: "1.1"
|
46
36
|
type: :runtime
|
47
37
|
version_requirements: *id002
|
@@ -53,9 +43,6 @@ dependencies:
|
|
53
43
|
requirements:
|
54
44
|
- - ~>
|
55
45
|
- !ruby/object:Gem::Version
|
56
|
-
segments:
|
57
|
-
- 0
|
58
|
-
- 1
|
59
46
|
version: "0.1"
|
60
47
|
type: :development
|
61
48
|
version_requirements: *id003
|
@@ -67,9 +54,6 @@ dependencies:
|
|
67
54
|
requirements:
|
68
55
|
- - ~>
|
69
56
|
- !ruby/object:Gem::Version
|
70
|
-
segments:
|
71
|
-
- 0
|
72
|
-
- 1
|
73
57
|
version: "0.1"
|
74
58
|
type: :development
|
75
59
|
version_requirements: *id004
|
@@ -87,13 +71,20 @@ files:
|
|
87
71
|
- README.markdown
|
88
72
|
- Rakefile
|
89
73
|
- lib/cuba/ron.rb
|
90
|
-
- lib/cuba/rum.rb
|
91
74
|
- lib/cuba/test.rb
|
92
75
|
- lib/cuba/version.rb
|
93
76
|
- lib/cuba.rb
|
94
77
|
- cuba.gemspec
|
78
|
+
- test/accept.rb
|
79
|
+
- test/captures.rb
|
80
|
+
- test/extension.rb
|
81
|
+
- test/helper.rb
|
95
82
|
- test/integration.rb
|
96
|
-
- test/
|
83
|
+
- test/number.rb
|
84
|
+
- test/on.rb
|
85
|
+
- test/path.rb
|
86
|
+
- test/run.rb
|
87
|
+
- test/segment.rb
|
97
88
|
has_rdoc: true
|
98
89
|
homepage: http://github.com/soveran/cuba
|
99
90
|
licenses: []
|
@@ -108,21 +99,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
99
|
requirements:
|
109
100
|
- - ">="
|
110
101
|
- !ruby/object:Gem::Version
|
111
|
-
segments:
|
112
|
-
- 0
|
113
102
|
version: "0"
|
114
103
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
104
|
none: false
|
116
105
|
requirements:
|
117
106
|
- - ">="
|
118
107
|
- !ruby/object:Gem::Version
|
119
|
-
segments:
|
120
|
-
- 0
|
121
108
|
version: "0"
|
122
109
|
requirements: []
|
123
110
|
|
124
111
|
rubyforge_project:
|
125
|
-
rubygems_version: 1.
|
112
|
+
rubygems_version: 1.5.2
|
126
113
|
signing_key:
|
127
114
|
specification_version: 3
|
128
115
|
summary: Rum based microframework for web applications.
|
data/lib/cuba/rum.rb
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
# Rum, the gRand Unified Mapper
|
2
|
-
#
|
3
|
-
# Rum is a powerful mapper for your Rack applications that can be used
|
4
|
-
# as a microframework.
|
5
|
-
#
|
6
|
-
# More information at http://github.com/chneukirchen/rum
|
7
|
-
#
|
8
|
-
# == Copyright
|
9
|
-
#
|
10
|
-
# Copyright (C) 2008, 2009 Christian Neukirchen <http://purl.org/net/chneukirchen>
|
11
|
-
#
|
12
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
13
|
-
# of this software and associated documentation files (the "Software"), to
|
14
|
-
# deal in the Software without restriction, including without limitation the
|
15
|
-
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16
|
-
# sell copies of the Software, and to permit persons to whom the Software is
|
17
|
-
# furnished to do so, subject to the following conditions:
|
18
|
-
#
|
19
|
-
# The above copyright notice and this permission notice shall be included in
|
20
|
-
# all copies or substantial portions of the Software.
|
21
|
-
#
|
22
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
25
|
-
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
26
|
-
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
27
|
-
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
28
|
-
#
|
29
|
-
require 'rack'
|
30
|
-
|
31
|
-
class Rack::Response
|
32
|
-
# 301 Moved Permanently
|
33
|
-
# 302 Found
|
34
|
-
# 303 See Other
|
35
|
-
# 307 Temporary Redirect
|
36
|
-
def redirect(target, status=302)
|
37
|
-
self.status = status
|
38
|
-
self["Location"] = target
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Rum
|
43
|
-
attr_reader :env, :req, :res
|
44
|
-
|
45
|
-
def initialize(&blk)
|
46
|
-
@blk = blk
|
47
|
-
end
|
48
|
-
|
49
|
-
def call(env)
|
50
|
-
dup._call(env)
|
51
|
-
end
|
52
|
-
|
53
|
-
def _call(env)
|
54
|
-
@env = env
|
55
|
-
@req = Rack::Request.new(env)
|
56
|
-
@res = Rack::Response.new
|
57
|
-
@matched = false
|
58
|
-
catch(:rum_run_next_app) {
|
59
|
-
instance_eval(&@blk)
|
60
|
-
@res.status = 404 unless @matched || !@res.empty?
|
61
|
-
return @res.finish
|
62
|
-
}.call(env)
|
63
|
-
end
|
64
|
-
|
65
|
-
def on(*arg, &block)
|
66
|
-
return if @matched
|
67
|
-
s, p = env["SCRIPT_NAME"], env["PATH_INFO"]
|
68
|
-
yield *arg.map { |a| a == true || (a != false && a.call) || return }
|
69
|
-
env["SCRIPT_NAME"], env["PATH_INFO"] = s, p
|
70
|
-
@matched = true
|
71
|
-
ensure
|
72
|
-
unless @matched
|
73
|
-
env["SCRIPT_NAME"], env["PATH_INFO"] = s, p
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def any(*args)
|
78
|
-
args.any? { |a| a == true || (a != false && a.call) }
|
79
|
-
end
|
80
|
-
|
81
|
-
def also
|
82
|
-
@matched = false
|
83
|
-
end
|
84
|
-
|
85
|
-
def path(p)
|
86
|
-
lambda {
|
87
|
-
if env["PATH_INFO"] =~ /\A\/(#{p})(\/|\z)/ #/
|
88
|
-
env["SCRIPT_NAME"] += "/#{$1}"
|
89
|
-
env["PATH_INFO"] = $2 + $'
|
90
|
-
$1
|
91
|
-
end
|
92
|
-
}
|
93
|
-
end
|
94
|
-
|
95
|
-
def number
|
96
|
-
path("\\d+")
|
97
|
-
end
|
98
|
-
|
99
|
-
def segment
|
100
|
-
path("[^\\/]+")
|
101
|
-
end
|
102
|
-
|
103
|
-
def extension(e="\\w+")
|
104
|
-
lambda { env["PATH_INFO"] =~ /\.(#{e})\z/ && $1 }
|
105
|
-
end
|
106
|
-
|
107
|
-
def param(p, default=nil)
|
108
|
-
lambda { req[p] || default }
|
109
|
-
end
|
110
|
-
|
111
|
-
def header(p, default=nil)
|
112
|
-
lambda { env[p.upcase.tr('-','_')] || default }
|
113
|
-
end
|
114
|
-
|
115
|
-
def default
|
116
|
-
true
|
117
|
-
end
|
118
|
-
|
119
|
-
def host(h)
|
120
|
-
req.host == h
|
121
|
-
end
|
122
|
-
|
123
|
-
def method(m)
|
124
|
-
req.request_method = m
|
125
|
-
end
|
126
|
-
|
127
|
-
def get; req.get?; end
|
128
|
-
def post; req.post?; end
|
129
|
-
def put; req.put?; end
|
130
|
-
def delete; req.delete?; end
|
131
|
-
|
132
|
-
def accept(mimetype)
|
133
|
-
lambda {
|
134
|
-
env['HTTP_ACCEPT'].split(',').any? { |s| s.strip == mimetype } and
|
135
|
-
res['Content-Type'] = mimetype
|
136
|
-
}
|
137
|
-
end
|
138
|
-
|
139
|
-
def check(&block)
|
140
|
-
block
|
141
|
-
end
|
142
|
-
|
143
|
-
def run(app)
|
144
|
-
throw :rum_run_next_app, app
|
145
|
-
end
|
146
|
-
|
147
|
-
def puts(*args)
|
148
|
-
args.each { |s|
|
149
|
-
res.write s
|
150
|
-
res.write "\n"
|
151
|
-
}
|
152
|
-
end
|
153
|
-
|
154
|
-
def print(*args)
|
155
|
-
args.each { |s| res.write s }
|
156
|
-
end
|
157
|
-
end
|
data/test/webrat.log
DELETED
@@ -1,5 +0,0 @@
|
|
1
|
-
# Logfile created on 2010-06-11 01:04:00 -0300 by logger.rb/20321
|
2
|
-
D, [2010-06-11T01:04:00.071479 #37917] DEBUG -- : REQUESTING PAGE: GET / with {} and HTTP headers {}
|
3
|
-
D, [2010-06-11T01:04:00.082487 #37917] DEBUG -- : REQUESTING PAGE: GET /login with {} and HTTP headers {"HTTP_REFERER"=>"/"}
|
4
|
-
D, [2010-06-11T01:04:00.084940 #37917] DEBUG -- : REQUESTING PAGE: POST /login with {"user"=>"Michel"} and HTTP headers {"HTTP_REFERER"=>"/login"}
|
5
|
-
D, [2010-06-11T01:04:00.087758 #37917] DEBUG -- : REQUESTING PAGE: GET / with {} and HTTP headers {"HTTP_REFERER"=>"/login"}
|