waves-edge 2009.03.10.13.14
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/waves +30 -0
- data/doc/HISTORY +1 -0
- data/doc/LICENSE +22 -0
- data/doc/README +1 -0
- data/doc/VERSION +1 -0
- data/lib/caches/file.rb +48 -0
- data/lib/caches/memcached.rb +40 -0
- data/lib/caches/simple.rb +25 -0
- data/lib/caches/synchronized.rb +25 -0
- data/lib/commands/console.rb +35 -0
- data/lib/commands/generate.rb +52 -0
- data/lib/commands/help.rb +5 -0
- data/lib/commands/server.rb +68 -0
- data/lib/dispatchers/base.rb +68 -0
- data/lib/dispatchers/default.rb +25 -0
- data/lib/ext/float.rb +13 -0
- data/lib/ext/hash.rb +31 -0
- data/lib/ext/integer.rb +27 -0
- data/lib/ext/kernel.rb +20 -0
- data/lib/ext/module.rb +20 -0
- data/lib/ext/object.rb +33 -0
- data/lib/ext/string.rb +20 -0
- data/lib/ext/symbol.rb +11 -0
- data/lib/ext/tempfile.rb +5 -0
- data/lib/foundations/classic.rb +59 -0
- data/lib/foundations/compact.rb +52 -0
- data/lib/helpers/basic.rb +11 -0
- data/lib/helpers/doc_type.rb +34 -0
- data/lib/helpers/extended.rb +21 -0
- data/lib/helpers/form.rb +42 -0
- data/lib/helpers/formatting.rb +30 -0
- data/lib/helpers/layouts.rb +37 -0
- data/lib/helpers/model.rb +37 -0
- data/lib/helpers/view.rb +22 -0
- data/lib/layers/inflect/english.rb +35 -0
- data/lib/layers/mvc.rb +41 -0
- data/lib/layers/mvc/controllers.rb +41 -0
- data/lib/layers/mvc/extensions.rb +52 -0
- data/lib/layers/orm/migration.rb +79 -0
- data/lib/layers/orm/providers/active_record.rb +84 -0
- data/lib/layers/orm/providers/active_record/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/active_record/tasks/generate.rb +28 -0
- data/lib/layers/orm/providers/active_record/tasks/schema.rb +22 -0
- data/lib/layers/orm/providers/data_mapper.rb +37 -0
- data/lib/layers/orm/providers/filebase.rb +25 -0
- data/lib/layers/orm/providers/sequel.rb +87 -0
- data/lib/layers/orm/providers/sequel/migrations/empty.rb.erb +9 -0
- data/lib/layers/orm/providers/sequel/tasks/generate.rb +30 -0
- data/lib/layers/orm/providers/sequel/tasks/schema.rb +16 -0
- data/lib/layers/renderers/erubis.rb +52 -0
- data/lib/layers/renderers/haml.rb +67 -0
- data/lib/layers/renderers/markaby.rb +41 -0
- data/lib/matchers/accept.rb +21 -0
- data/lib/matchers/base.rb +30 -0
- data/lib/matchers/content_type.rb +17 -0
- data/lib/matchers/path.rb +67 -0
- data/lib/matchers/query.rb +21 -0
- data/lib/matchers/request.rb +27 -0
- data/lib/matchers/resource.rb +19 -0
- data/lib/matchers/traits.rb +19 -0
- data/lib/matchers/uri.rb +20 -0
- data/lib/renderers/mixin.rb +13 -0
- data/lib/resources/mixin.rb +136 -0
- data/lib/resources/paths.rb +132 -0
- data/lib/runtime/configuration.rb +100 -0
- data/lib/runtime/console.rb +23 -0
- data/lib/runtime/logger.rb +35 -0
- data/lib/runtime/mime_types.rb +536 -0
- data/lib/runtime/mocks.rb +14 -0
- data/lib/runtime/monitor.rb +32 -0
- data/lib/runtime/request.rb +152 -0
- data/lib/runtime/response.rb +43 -0
- data/lib/runtime/response_mixin.rb +54 -0
- data/lib/runtime/runtime.rb +69 -0
- data/lib/runtime/server.rb +20 -0
- data/lib/runtime/session.rb +27 -0
- data/lib/runtime/worker.rb +86 -0
- data/lib/servers/base.rb +42 -0
- data/lib/servers/mongrel.rb +13 -0
- data/lib/servers/webrick.rb +13 -0
- data/lib/tasks/gem.rb +32 -0
- data/lib/tasks/generate.rb +85 -0
- data/lib/views/errors.rb +49 -0
- data/lib/views/mixin.rb +64 -0
- data/lib/waves.rb +63 -0
- data/samples/blog/Rakefile +25 -0
- data/samples/blog/configurations/default.rb +11 -0
- data/samples/blog/configurations/development.rb +29 -0
- data/samples/blog/configurations/production.rb +26 -0
- data/samples/blog/models/comment.rb +23 -0
- data/samples/blog/models/entry.rb +31 -0
- data/samples/blog/public/css/site.css +13 -0
- data/samples/blog/public/javascript/jquery-1.2.6.min.js +32 -0
- data/samples/blog/public/javascript/site.js +13 -0
- data/samples/blog/resources/entry.rb +39 -0
- data/samples/blog/resources/map.rb +9 -0
- data/samples/blog/schema/migrations/001_initial_schema.rb +17 -0
- data/samples/blog/schema/migrations/002_add_comments.rb +18 -0
- data/samples/blog/schema/migrations/templates/empty.rb.erb +9 -0
- data/samples/blog/startup.rb +8 -0
- data/samples/blog/templates/comment/add.mab +12 -0
- data/samples/blog/templates/comment/list.mab +6 -0
- data/samples/blog/templates/entry/edit.mab +14 -0
- data/samples/blog/templates/entry/list.mab +16 -0
- data/samples/blog/templates/entry/show.mab +18 -0
- data/samples/blog/templates/entry/summary.mab +9 -0
- data/samples/blog/templates/errors/not_found_404.mab +7 -0
- data/samples/blog/templates/errors/server_error_500.mab +2 -0
- data/samples/blog/templates/layouts/default.mab +19 -0
- data/samples/blog/templates/waves/status.mab +85 -0
- data/templates/classic/Rakefile +90 -0
- data/templates/classic/configurations/default.rb.erb +9 -0
- data/templates/classic/configurations/development.rb.erb +26 -0
- data/templates/classic/configurations/production.rb.erb +29 -0
- data/templates/classic/controllers/.gitignore +0 -0
- data/templates/classic/helpers/.gitignore +0 -0
- data/templates/classic/lib/tasks/.gitignore +0 -0
- data/templates/classic/models/.gitignore +0 -0
- data/templates/classic/public/css/.gitignore +0 -0
- data/templates/classic/public/flash/.gitignore +0 -0
- data/templates/classic/public/images/.gitignore +0 -0
- data/templates/classic/public/javascript/.gitignore +0 -0
- data/templates/classic/resources/.gitignore +0 -0
- data/templates/classic/resources/map.rb.erb +8 -0
- data/templates/classic/schema/migrations/.gitignore +0 -0
- data/templates/classic/startup.rb.erb +11 -0
- data/templates/classic/templates/errors/not_found_404.mab +7 -0
- data/templates/classic/templates/errors/server_error_500.mab +7 -0
- data/templates/classic/templates/layouts/default.mab +14 -0
- data/templates/classic/tmp/sessions/.gitignore +0 -0
- data/templates/classic/views/.gitignore +0 -0
- data/templates/compact/startup.rb.erb +11 -0
- data/test/ext/object.rb +55 -0
- data/test/ext/shortcuts.rb +73 -0
- data/test/helpers.rb +17 -0
- data/test/match/accept.rb +34 -0
- data/test/match/methods.rb +22 -0
- data/test/match/params.rb +33 -0
- data/test/match/path.rb +106 -0
- data/test/match/query.rb +40 -0
- data/test/process/request.rb +75 -0
- data/test/process/resource.rb +53 -0
- data/test/resources/path.rb +166 -0
- data/test/runtime/configurations.rb +19 -0
- data/test/runtime/request.rb +63 -0
- data/test/runtime/response.rb +55 -0
- data/test/views/views.rb +34 -0
- metadata +394 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module <%= @name %>
|
2
|
+
|
3
|
+
module Configurations
|
4
|
+
|
5
|
+
class Development < Default
|
6
|
+
|
7
|
+
database :adapter => 'sqlite', :database => '<%= @name.downcase %>'
|
8
|
+
|
9
|
+
reloadable [ <%= @name %> ]
|
10
|
+
log :level => :debug
|
11
|
+
host '127.0.0.1'
|
12
|
+
port 3000
|
13
|
+
dependencies []
|
14
|
+
|
15
|
+
application do
|
16
|
+
use ::Rack::ShowExceptions
|
17
|
+
use ::Rack::Static, :urls => [ '/css/', '/javascript/', '/favicon.ico' ], :root => 'public'
|
18
|
+
run ::Waves::Dispatchers::Default.new
|
19
|
+
end
|
20
|
+
|
21
|
+
server Waves::Servers::Mongrel
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module <%= @name %>
|
2
|
+
|
3
|
+
module Configurations
|
4
|
+
|
5
|
+
class Production < Default
|
6
|
+
|
7
|
+
database :host => 'localhost', :adapter => 'mysql', :database => '<%= @name.downcase %>',
|
8
|
+
:user => 'root', :password => ''
|
9
|
+
|
10
|
+
reloadable []
|
11
|
+
|
12
|
+
log :level => :error,
|
13
|
+
:output => ( :log / "waves.#{$$}" ),
|
14
|
+
:rotation => :weekly
|
15
|
+
|
16
|
+
host '0.0.0.0'
|
17
|
+
|
18
|
+
port 80
|
19
|
+
|
20
|
+
application do
|
21
|
+
use ::Rack::Static, :urls => [ '/css/', '/javascript/', '/favicon.ico' ], :root => 'public'
|
22
|
+
run ::Waves::Dispatchers::Default.new
|
23
|
+
end
|
24
|
+
|
25
|
+
server Waves::Servers::Mongrel
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,7 @@
|
|
1
|
+
style <<-STYLE
|
2
|
+
body { background: #c93; padding: 20px; font-family: verdana, sans-serif; }
|
3
|
+
h1 { font-size: 60px; font-weight: bold; margin: 0px; }
|
4
|
+
p { font-size: 24px; margin: 0px; }
|
5
|
+
STYLE
|
6
|
+
h1 '500'
|
7
|
+
p %q( Internal server error. Sorry, but your request could not be processed. )
|
File without changes
|
File without changes
|
data/test/ext/object.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../helpers.rb"
|
2
|
+
|
3
|
+
describe "Object#cache_method_missing" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
class A; end
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Object.instance_eval { remove_const(:A) if const_defined?(:A) }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "defines the missing method" do
|
14
|
+
A.module_eval do
|
15
|
+
def method_missing(name, *args)
|
16
|
+
cache_method_missing name, "'hi'", *args
|
17
|
+
end
|
18
|
+
end
|
19
|
+
A.new.bar
|
20
|
+
A.new.should.respond_to :bar
|
21
|
+
end
|
22
|
+
|
23
|
+
it "passes along the args" do
|
24
|
+
A.module_eval do
|
25
|
+
def method_missing(name, *args, &block)
|
26
|
+
cache_method_missing name, "args.join('-')", *args
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
A.new.bar(1, 2, 3).should == "1-2-3"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "passes along the block" do
|
34
|
+
A.module_eval do
|
35
|
+
def method_missing(name, *args, &block)
|
36
|
+
cache_method_missing name, "block.call", *args, &block
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
A.new.bar { 'bye' }.should == 'bye'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "Object#instance_exec" do
|
46
|
+
|
47
|
+
before do
|
48
|
+
@block = lambda { |guy| "Howdy, #{guy}!" }
|
49
|
+
end
|
50
|
+
|
51
|
+
it "works like instance_eval, but it takes args and gives them to the block" do
|
52
|
+
instance_exec( "Steve", &@block ).should == "Howdy, Steve!"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../helpers.rb"
|
2
|
+
|
3
|
+
describe "Waves::Ext::String" do
|
4
|
+
it "defines / as syntactic sugar for File.join" do
|
5
|
+
( "lib" / "utilities" ).should == File.join( "lib", "utilities" )
|
6
|
+
( "lib" / :utilities ).should == File.join( "lib", "utilities" )
|
7
|
+
( "lib" / 3 ).should == File.join( "lib", "3" )
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "A monkeypatch to Symbol" do
|
12
|
+
|
13
|
+
it "defines / as syntactic sugar for File.join" do
|
14
|
+
( :lib / :utilities ).should == File.join( "lib", "utilities")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "Waves::Ext::Hash" do
|
20
|
+
|
21
|
+
it "adds a non-destructive method for converting all hash keys to strings" do
|
22
|
+
h = { :a => 1, 'b' => 2, 3 => 3}
|
23
|
+
h.stringify_keys.should == { 'a' => 1, 'b' => 2, '3' => 3}
|
24
|
+
h.should == { :a => 1, 'b' => 2, 3 => 3}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "adds a destructive method for converting hash keys to symbols" do
|
28
|
+
h = { "two" => 2, :three => 3}
|
29
|
+
h.symbolize_keys!
|
30
|
+
h.should == { :two => 2, :three => 3 }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "Waves::Ext::Integer" do
|
36
|
+
|
37
|
+
it "has an absolutely pedantic amount of helpers" do
|
38
|
+
1.kilobytes.should == "1_024".to_i
|
39
|
+
1.megabytes.should == "1_048_576".to_i
|
40
|
+
1.gigabytes.should == "1_073_741_824".to_i
|
41
|
+
1.terabytes.should == "1_099_511_627_776".to_i
|
42
|
+
1.petabytes.should == "1_125_899_906_842_624".to_i
|
43
|
+
1.exabytes.should == "1_152_921_504_606_846_976".to_i
|
44
|
+
1.zettabytes.should == "1_180_591_620_717_411_303_424".to_i
|
45
|
+
1.yottabytes.should == "1_208_925_819_614_629_174_706_176".to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Waves::Ext::Module" do
|
51
|
+
|
52
|
+
before do
|
53
|
+
module Eenie; module Meenie; module Miney; end; end ; end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "defines a basename method" do
|
57
|
+
Eenie::Meenie.basename.should == "Meenie"
|
58
|
+
Eenie::Meenie::Miney.basename.should == "Miney"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "defines [] for easy access to namespaced constants" do
|
62
|
+
Eenie[:Meenie].should == Eenie::Meenie
|
63
|
+
end
|
64
|
+
|
65
|
+
it "defines a method for obtaining the outermost constant name" do
|
66
|
+
Eenie::Meenie::Miney.rootname.should == "Eenie"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "defines a method for obtaining the outermost constant" do
|
70
|
+
Eenie::Meenie::Miney.root.should == Eenie
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
data/test/helpers.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'; %w{ bacon facon }.each { |dep| require dep }
|
2
|
+
|
3
|
+
# Framework lib goes to the front of the loadpath
|
4
|
+
$:.unshift('lib')
|
5
|
+
require 'waves'
|
6
|
+
require 'runtime/mocks'
|
7
|
+
|
8
|
+
Waves::Runtime.instance = Waves::Runtime.new
|
9
|
+
|
10
|
+
Bacon::Context.module_eval do
|
11
|
+
include Waves::Mocks
|
12
|
+
alias_method :specification, :describe
|
13
|
+
alias_method :feature, :it
|
14
|
+
end
|
15
|
+
|
16
|
+
Bacon.extend Bacon::TestUnitOutput
|
17
|
+
Bacon.summary_on_exit
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
|
2
|
+
require 'foundations/compact'
|
3
|
+
|
4
|
+
describe "Matching The Accepts Header" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
Test = Module.new { include Waves::Foundations::Compact }
|
8
|
+
Waves << Test
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Waves.applications.clear
|
13
|
+
Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
|
14
|
+
end
|
15
|
+
|
16
|
+
feature "Match an implied accept header using the file extension" do
|
17
|
+
Test::Resources::Map.on( :get, true, :accept => :javascript ) {}
|
18
|
+
get("/foo.js").status.should == 200
|
19
|
+
get("/foo").status.should == 404
|
20
|
+
end
|
21
|
+
|
22
|
+
feature "Match against an array of options" do
|
23
|
+
Test::Resources::Map.on( :get, true, :accept => [ :javascript, :css ] ) {}
|
24
|
+
get("/foo.js").status.should == 200
|
25
|
+
get("/foo").status.should == 404
|
26
|
+
end
|
27
|
+
|
28
|
+
feature "Match against a Mime type (rather than subtype)" do
|
29
|
+
Test::Resources::Map.on( :get, true, :accept => :image ) {}
|
30
|
+
get("/foo.png").status.should == 200
|
31
|
+
get("/foo").status.should == 404
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
|
2
|
+
require 'foundations/compact'
|
3
|
+
|
4
|
+
describe "Matching Request Methods" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
Test = Module.new { include Waves::Foundations::Compact }
|
8
|
+
Test::Resources::Map.module_eval {
|
9
|
+
%w( get put post delete head ).each { |m| on( m ) { m } } }
|
10
|
+
Waves << Test
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
Waves.applications.clear
|
15
|
+
Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
|
16
|
+
end
|
17
|
+
|
18
|
+
%w( get put post delete head ).each do |m|
|
19
|
+
feature( "Match the '#{m}' method" ) { send( m, '/' ).body.should == m }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
|
2
|
+
require 'foundations/compact'
|
3
|
+
|
4
|
+
describe "A resource that has matched a request" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
Test = Module.new { include Waves::Foundations::Compact }
|
8
|
+
Waves << Test
|
9
|
+
|
10
|
+
@request = Waves::Request.new( env('http://localhost/baz?bar=7', :method => 'GET' ) )
|
11
|
+
Test::Resources::Map.on( :get, [ :foo ] ) {}
|
12
|
+
@resource = Test::Resources::Map.new( @request )
|
13
|
+
@resource.get
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
Waves.applications.clear
|
18
|
+
Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "makes parameters captured from the path available as #captured" do
|
22
|
+
@resource.captured.to_h.should == { 'foo' => 'baz' }
|
23
|
+
end
|
24
|
+
|
25
|
+
it "makes http query parameters available as #query" do
|
26
|
+
@resource.query.to_h.should == { 'bar' => '7' }
|
27
|
+
end
|
28
|
+
|
29
|
+
it "provides access to all derived parameters using #params" do
|
30
|
+
@resource.params.to_h.should == { 'foo' => 'baz', 'bar' => '7' }
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/test/match/path.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../test/helpers.rb"
|
2
|
+
require "foundations/compact"
|
3
|
+
|
4
|
+
describe "Matching Request URIs" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
Test = Module.new { include Waves::Foundations::Compact }
|
8
|
+
Waves << Test
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
Waves.applications.clear
|
13
|
+
Object.instance_eval { remove_const(:Test) if const_defined?(:Test) }
|
14
|
+
end
|
15
|
+
|
16
|
+
feature "By default, we match an arbitrary path." do
|
17
|
+
Test::Resources::Map.on( :get ) {}
|
18
|
+
get("/foobar").status.should == 200
|
19
|
+
get("/foo/bar").status.should == 200
|
20
|
+
end
|
21
|
+
|
22
|
+
feature "A path of true matches an arbitrary path." do
|
23
|
+
Test::Resources::Map.on( :get, true ) { request.path }
|
24
|
+
get("/foobar").body.should == '/foobar'
|
25
|
+
get("/foo/bar").body.should == '/foo/bar'
|
26
|
+
end
|
27
|
+
|
28
|
+
feature "An empty path matches root." do
|
29
|
+
Test::Resources::Map.on( :get, [] ) { request.path }
|
30
|
+
get("/").body.should == '/'
|
31
|
+
end
|
32
|
+
|
33
|
+
feature "A string path component matches that string." do
|
34
|
+
Test::Resources::Map.on( :get, [ 'foo' ] ) { request.path }
|
35
|
+
get("/foo").body.should == '/foo'
|
36
|
+
get("/bar").status.should == 404
|
37
|
+
end
|
38
|
+
|
39
|
+
feature "A symbol path component captures that component using the symbol as a key." do
|
40
|
+
Test::Resources::Map.on( :get, [ :foo ] ) { captured[:foo] }
|
41
|
+
get("/foo").body.should == 'foo'
|
42
|
+
get("/bar").body.should == 'bar'
|
43
|
+
end
|
44
|
+
|
45
|
+
feature "A regexp path component matches the any component that matches the regexp." do
|
46
|
+
Test::Resources::Map.on( :get, [ /\d+/ ] ) { request.path }
|
47
|
+
get("/1234").body.should == '/1234'
|
48
|
+
get("/foo").status.should == 404
|
49
|
+
end
|
50
|
+
|
51
|
+
feature "A path component of true matches the remaining path." do
|
52
|
+
Test::Resources::Map.on( :get, [ 'foo', true ] ) { request.path }
|
53
|
+
get("/foo/bar/baz").body.should == '/foo/bar/baz'
|
54
|
+
get("/foo").status.should == 404
|
55
|
+
end
|
56
|
+
|
57
|
+
[["one or more", 1..-1, false, true, true],
|
58
|
+
["zero or more", 0..-1, true, true, true],
|
59
|
+
["one to N (N=2)", 1..2, false, true, true, false],
|
60
|
+
["one to N (N=3)", 1..3, false, true, true, true, false]
|
61
|
+
].each do |name, range, *tests|
|
62
|
+
feature "A Range path component can match #{name} components" do
|
63
|
+
Test::Resources::Map.on(:get, ['foo', range]) { request.path }
|
64
|
+
tests.size.times do |i|
|
65
|
+
get("/foo" * ( i + 1 ) ).status.should == (tests[i] ? 200 : 404)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
feature "A path component can use a hash with a value of true to capture the remaining path." do
|
71
|
+
Test::Resources::Map.on( :get, [ 'foo', { :rest => true } ] ) { captured[:rest] * ' ' }
|
72
|
+
get("/foo/bar/baz").body.should == 'bar baz'
|
73
|
+
end
|
74
|
+
|
75
|
+
[["one or more", 1..-1, false, 'foo', 'foo foo'],
|
76
|
+
["zero or more", 0..-1, '', 'foo', 'foo foo'],
|
77
|
+
["one to N (N=2)", 1..2, false, 'foo', 'foo foo', false],
|
78
|
+
["one to N (N=3)", 0..3, '', 'foo', 'foo foo', 'foo foo foo', false]
|
79
|
+
].each do |name, range, *tests|
|
80
|
+
feature "A Range path component can match #{name} components" do
|
81
|
+
Test::Resources::Map.on(:get, ['foo', { :rest => range }]) { captured.rest * ' ' }
|
82
|
+
tests.size.times do |i|
|
83
|
+
response = get("/foo" * ( i + 1 ) )
|
84
|
+
tests[i] ? response.body.should == tests[i] : response.status.should == 404
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
feature "A path component can use a hash with a string value to provide a default." do
|
90
|
+
Test::Resources::Map.on( :get, [ 'foo', { :bar => 'bar' } ] ) { captured[:bar] }
|
91
|
+
get("/foo/baz").body.should == 'baz'
|
92
|
+
get("/foo").body.should == 'bar'
|
93
|
+
end
|
94
|
+
|
95
|
+
feature "A path component can use a hash with a regexp value to match and capture." do
|
96
|
+
Test::Resources::Map.on( :get, [ 'foo', { :bar => /\d+/ } ] ) { captured[:bar] }
|
97
|
+
get("/foo/123").body.should == '123'
|
98
|
+
get("/foo").status.should == 404
|
99
|
+
end
|
100
|
+
|
101
|
+
it "Path components match against unescaped values" do
|
102
|
+
Test::Resources::Map.on(:get, [ 'polar bear']) { 'bang' }
|
103
|
+
get("/polar%20bear").body.should == 'bang'
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|