pakada-dispatch 0.0.1

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/.project ADDED
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>pakada-dispatch</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ </buildSpec>
9
+ <natures>
10
+ <nature>com.aptana.ruby.core.rubynature</nature>
11
+ </natures>
12
+ </projectDescription>
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "awesome_print"
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Lars Gierth
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ Routing And Action Controllers For Pakada
2
+ ===================================================
3
+
4
+ TODO: Write documentation
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler"
2
+ Bundler.setup :development
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ task :default => :spec
7
+ RSpec::Core::RakeTask.new :spec
8
+
9
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1 @@
1
+ require "pakada/dispatch"
@@ -0,0 +1,43 @@
1
+ require "pakada"
2
+ require "rack/mount"
3
+
4
+ require "pakada/dispatch/controller"
5
+ require "pakada/dispatch/module"
6
+ require "pakada/dispatch/version"
7
+
8
+ class Pakada
9
+ class Dispatch
10
+ include Pakada::Module
11
+
12
+ attr_reader :router
13
+
14
+ def initialize
15
+ @router = Rack::Mount::RouteSet.new
16
+ end
17
+
18
+ before :boot, :apply_dispatch_patches, :before => :all, do |ctx|
19
+ Pakada.modules.each_value do |m|
20
+ m.singleton_class.send :include, Pakada::Dispatch::Module
21
+ end
22
+ end
23
+
24
+ before :boot, :load_controllers do |ctx|
25
+ Pakada.modules.each_value do |mod|
26
+ mod.load_controllers
27
+ end
28
+ Pakada.hooking.invoke :routing
29
+ end
30
+
31
+ before :boot, :set_dispatch_app do |ctx|
32
+ Pakada.app = proc {|env| hookable :dispatch, env }
33
+ end
34
+
35
+ after :boot, :freeze_router do |ctx|
36
+ router.rehash
37
+ end
38
+
39
+ hookable :dispatch do |ctx|
40
+ ctx.result = router.call ctx.args
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,53 @@
1
+ class Pakada
2
+ class Dispatch
3
+ Action = Struct.new :block, :options
4
+
5
+ module Controller
6
+ def self.build(&block)
7
+ Class.new do
8
+ include Controller
9
+ instance_eval &block if block
10
+ end
11
+ end
12
+
13
+ attr_reader :request, :response, :params, :options
14
+
15
+ def initialize(env)
16
+ @request, @response = Rack::Request.new(env), Rack::Response.new
17
+ @params = request.env["rack.routing_args"] || {}
18
+ end
19
+
20
+ def call_action(name, options = {})
21
+ action = self.class.actions[name]
22
+ raise ArgumentError, "No such action - #{name}" unless action
23
+
24
+ @options = action.options.merge options
25
+ instance_eval &action.block
26
+ end
27
+
28
+ module ClassMethods
29
+ def actions
30
+ @actions ||= {}
31
+ end
32
+
33
+ def action(name, options = {}, &block)
34
+ if block
35
+ actions[name] = Action.new block, options
36
+ elsif actions[name]
37
+ proc do |env|
38
+ controller = new env
39
+ controller.call_action name, options
40
+ controller.response.finish
41
+ end
42
+ else
43
+ proc {|env| [404, {"X-Cascade" => "pass"}, []] }
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.included(klass)
49
+ klass.extend ClassMethods
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,70 @@
1
+ class Pakada
2
+ class Dispatch
3
+ module Module
4
+ attr_reader :controllers
5
+
6
+ def load_controllers
7
+ @controllers = {}
8
+ Dir["#{path}/controllers/*.rb"].each do |file|
9
+ next unless file.match %r{.*/[a-z0-9_]+\.rb$}
10
+ name = file.split("/").last.split(".").first
11
+ @controllers[name.to_sym] = Controller.build do
12
+ instance_eval File.read(file), file, 1
13
+ end
14
+ end if path
15
+ end
16
+
17
+ def route(name = nil, opts)
18
+ route = opts.keys.find {|k| !k.kind_of? Symbol }
19
+ target = opts.delete route
20
+ splats = []
21
+ unless route.is_a? Regexp
22
+ route = route.gsub(/\((.*)\)/, '(\1)?')
23
+ .gsub(/:([a-z0-9\-_]+)/, '(?<\1>[a-z0-9\-_]+)')
24
+ .gsub(/\*([a-z0-9\-_]+)/) do |match|
25
+ splats << $1.to_sym
26
+ '(?<' + $1 + '>([a-z0-9\-_]/?)*)'
27
+ end
28
+ route = Regexp.compile "^#{route}$"
29
+ end
30
+
31
+ defaults = opts.dup
32
+ target = "::" + target unless target.include? "::"
33
+ target = target + "#" unless target.include? "#"
34
+ parts = target.split /::|#/
35
+ defaults[:module] = parts[0].to_sym unless !parts[0] || parts[0].empty?
36
+ defaults[:controller] = parts[1].to_sym unless !parts[1] || parts[1].empty?
37
+ defaults[:action] = parts[2].to_sym unless !parts[2] || parts[2].empty?
38
+
39
+ app = proc do |env|
40
+ env["pakada.dispatch.route"] = name
41
+ params = env["pakada.dispatch.params"] = env["rack.routing_args"].dup
42
+
43
+ params.each_pair do |key, value|
44
+ if splats.include? key
45
+ params[key] = value.split("/").select {|v| !v.empty? }
46
+ end
47
+ if [:module, :controller, :action].include? key
48
+ params[key] = value.to_sym
49
+ end
50
+ end
51
+
52
+ mod = Pakada[params[:module]]
53
+ controller = mod.controllers[params[:controller].to_sym] if mod
54
+ if controller
55
+ controller.action(params[:action].to_sym).call env
56
+ else
57
+ [404, {"X-Cascade" => "pass"}, []]
58
+ end
59
+ end
60
+
61
+ defaults[:module] = module_name unless defaults[:module]
62
+ Pakada[:dispatch].router.add_route app, {:path_info => route}, defaults, name
63
+ end
64
+ end
65
+
66
+ def url(*args)
67
+ router.url({}, *args)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,5 @@
1
+ class Pakada
2
+ class Dispatch
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "pakada/dispatch/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pakada-dispatch"
7
+ s.version = Pakada::Dispatch::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Lars Gierth"]
10
+ s.email = ["lars.gierth@gmail.com"]
11
+ s.homepage = "https://rubygems.org/gems/pakada-dispatch"
12
+ s.summary = %q{Routing And Action Controllers For Pakada}
13
+ #s.description = %q{TODO: Write a gem description}
14
+
15
+ s.add_dependency "pakada"
16
+ s.add_dependency "rack-mount"
17
+
18
+ s.add_development_dependency "rspec"
19
+ s.add_development_dependency "fakefs"
20
+
21
+ s.files = `git ls-files`.split("\n") - [".gitignore", ".rvmrc"]
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,138 @@
1
+ require "spec_helper"
2
+
3
+ describe Pakada::Dispatch::Controller do
4
+ describe ".build" do
5
+ it "builds an empty controller class" do
6
+ subject.build.should respond_to(:action)
7
+ subject.build.should have(0).actions
8
+ end
9
+
10
+ describe "when called with a block" do
11
+ it "executes the block in the class' context" do
12
+ subject.build { action(:foo) {} }.should have(1).actions
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "SomeController" do
19
+ subject do
20
+ Pakada::Dispatch::Controller.build
21
+ end
22
+
23
+ describe ".action" do
24
+ describe "when called with a block" do
25
+ it "adds an action to the controller" do
26
+ block = proc {}
27
+ subject.action :foo, &block
28
+ subject.actions[:foo].options.should == {}
29
+ subject.actions[:foo].block.should == block
30
+ end
31
+ end
32
+
33
+ describe "when called with a block and a hash" do
34
+ it "adds an action with options" do
35
+ options = double "options"
36
+ block = proc {}
37
+ subject.action :foo, options, &block
38
+ subject.actions[:foo].options.should == options
39
+ end
40
+ end
41
+
42
+ describe "when called without a block" do
43
+ it "builds a Rack end-point" do
44
+ subject.action(:foo) {}
45
+
46
+ env = {"foo" => "123"}
47
+ options = {:key => :value}
48
+ response = stub "response", :finish => [200, {}, []]
49
+ controller = stub "controller", :response => response
50
+
51
+ subject.should_receive(:new).twice.with(env) { controller }
52
+
53
+ controller.should_receive(:call_action).once.with(:foo, {})
54
+ subject.action(:foo).call(env).should == response.finish
55
+
56
+ controller.should_receive(:call_action).once.with(:foo, options)
57
+ subject.action(:foo, options).call(env)
58
+ end
59
+
60
+ describe "when called with the name of a non-existing action" do
61
+ it "builds an X-Cascade: pass app" do
62
+ subject.action(:foo).call({}).should == [
63
+ 404, {"X-Cascade" => "pass"}, []]
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "#initialize" do
70
+ it "sets up Rack::Request and Response objects" do
71
+ env = {"foo" => "123"}
72
+ controller = subject.new env
73
+
74
+ controller.request.env.should == env
75
+ controller.response.should respond_to(:finish)
76
+ end
77
+
78
+ it "populates #params with the routing parameters" do
79
+ params = {:foo => :bar}
80
+ controller = subject.new "rack.routing_args" => params
81
+ controller.params.should == params
82
+
83
+ controller = subject.new({})
84
+ controller.params.should == {}
85
+ end
86
+ end
87
+
88
+ describe "#call_action" do
89
+ it "invokes the action's block in the controller's scope" do
90
+ subject.action(:foo) { do_something }
91
+ controller = subject.new({})
92
+ controller.should_receive :do_something
93
+
94
+ controller.call_action :foo
95
+ end
96
+
97
+ it "populates #options" do
98
+ subject.action(:foo, :key => :value) {}
99
+ controller = subject.new({})
100
+
101
+ controller.call_action :foo
102
+ controller.options[:key].should == :value
103
+ end
104
+
105
+ describe "when called with the name of a non-existing action" do
106
+ it "raises an error" do
107
+ controller = subject.new({})
108
+ proc { controller.call_action :foo }.should raise_error(ArgumentError)
109
+ end
110
+ end
111
+
112
+ describe "when called with a hash" do
113
+ it "overrides the action's options" do
114
+ subject.action(:foo, :key => :value) {}
115
+ controller = subject.new({})
116
+
117
+ controller.call_action :foo, :key => :value2
118
+ controller.options[:key].should == :value2
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ describe Pakada::Dispatch::Action do
125
+ describe "#block" do
126
+ it "returns the action's code block" do
127
+ block = double "block"
128
+ Pakada::Dispatch::Action.new(block).block.should == block
129
+ end
130
+ end
131
+
132
+ describe "#options" do
133
+ it "returns the actions' options hash" do
134
+ options = double "options"
135
+ Pakada::Dispatch::Action.new(nil, options).options.should == options
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,80 @@
1
+ require "spec_helper"
2
+
3
+ describe Pakada::Dispatch do
4
+ subject { Pakada::Dispatch.new }
5
+
6
+ it "is a Pakada module" do
7
+ subject.module_name.should == :dispatch
8
+ end
9
+
10
+ describe ".initialize" do
11
+ it "initializes the router" do
12
+ subject.router.should respond_to :add_route
13
+ subject.router.should respond_to :call
14
+ end
15
+ end
16
+
17
+ describe ".before(:boot, :apply_dispatch_patches)" do
18
+ before do
19
+ Pakada.load_modules
20
+ Pakada.load_hooking
21
+ end
22
+
23
+ it "freedom-patches all loaded modules" do
24
+ Pakada.hooking.invoke :boot
25
+ Pakada.modules.each_value do |m|
26
+ modules = m.singleton_class.included_modules
27
+ modules.should include(Pakada::Dispatch::Module)
28
+ end
29
+ end
30
+ end
31
+
32
+ describe ".before(:boot, :load_controllers)" do
33
+ before do
34
+ Pakada.load_modules
35
+ Pakada.load_hooking
36
+ end
37
+
38
+ it "calls .load_controllers on each module" do
39
+ Pakada.modules.each_value do |mod|
40
+ mod.should_receive :load_controllers
41
+ end
42
+ Pakada.hooking.invoke :boot
43
+ end
44
+ end
45
+
46
+ describe ".before(:boot, :set_dispatch_app)" do
47
+ it "overwrites Pakada.app with its own app" do
48
+ Pakada.load_modules
49
+ Pakada.load_hooking
50
+ Pakada.hooking.invoke :boot
51
+
52
+ req = {"key" => "value"}
53
+ resp = [200, {}, []]
54
+ Pakada.hooking.should_receive(:invoke).with(:dispatch, req) { resp }
55
+ Pakada.app.call(req).should == resp
56
+ end
57
+ end
58
+
59
+ describe ".before(:boot, :freeze_router)" do
60
+ it "freezes the router" do
61
+ Pakada.load_modules
62
+ Pakada.load_hooking
63
+
64
+ Pakada[:dispatch].router.should_receive :rehash
65
+ Pakada.hooking.invoke :boot
66
+ end
67
+ end
68
+
69
+ describe ".hookable(:dispatch)" do
70
+ it "passes the request to the router" do
71
+ Pakada.load_modules
72
+ Pakada.load_hooking
73
+
74
+ req = {"key" => "value"}
75
+ resp = [200, {}, []]
76
+ Pakada[:dispatch].router.should_receive(:call).with(req) { resp }
77
+ Pakada.hooking.invoke(:dispatch, req).should == resp
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,298 @@
1
+ require "spec_helper"
2
+
3
+ describe Pakada::Dispatch::Module do
4
+ describe "#load_controllers" do
5
+ before do
6
+ FakeFS.activate!
7
+ end
8
+
9
+ subject do
10
+ FileUtils.mkdir_p "/mymodule/controllers"
11
+ File.open "/mymodule/controllers/foo.rb", "w" do |f|
12
+ f.write "action(:foo) {}"
13
+ end
14
+
15
+ Class.new do
16
+ @module_name, @path = :foo, "/mymodule"
17
+ include Pakada::Module
18
+ include Pakada::Dispatch::Module
19
+ end.new
20
+ end
21
+
22
+ it "iterates over the module's controllers/ directory and builds a controller for each file" do
23
+ subject.load_controllers
24
+ subject.controllers[:foo].should have(1).actions
25
+ end
26
+
27
+ it "does nothing if the module doesn't have a path" do
28
+ subject.class.instance_variable_set :@path, nil
29
+ subject.load_controllers
30
+ subject.should have(0).controllers
31
+ end
32
+
33
+ after do
34
+ FakeFS.deactivate!
35
+ FakeFS::FileSystem.clear
36
+
37
+ Pakada::Module.descendants.delete :foo
38
+ end
39
+ end
40
+
41
+ describe "#route" do
42
+ describe "when called without a symbol" do
43
+ it "creates an anonymous route" do
44
+ Pakada.boot
45
+
46
+ Pakada[:dispatch].router.should_receive(:add_route) do |*args|
47
+ args[0].should respond_to(:call)
48
+ args[1][:path_info].should be_a(Regexp)
49
+ args[2].should == {
50
+ :module => :dispatch,
51
+ :controller => :foo,
52
+ :action => :bar
53
+ }
54
+ args[3].should be_nil
55
+ end
56
+ Pakada[:dispatch].route "/pattern" => "foo#bar"
57
+ end
58
+ end
59
+
60
+ describe "takes a hash that" do
61
+ before { Pakada.boot }
62
+
63
+ subject { Pakada[:dispatch] }
64
+
65
+ it "contains a route-pattern => target-action pair" do
66
+ subject.router.should_receive(:add_route) do |*args|
67
+ args[0].should respond_to(:call)
68
+ args[1][:path_info].should == %r{^/pattern$}
69
+ args[2].should == {
70
+ :module => :foo,
71
+ :controller => :bar,
72
+ :action => :baz
73
+ }
74
+ args[3].should == :myroute
75
+ end
76
+ subject.route :myroute, "/pattern" => "foo::bar#baz"
77
+ end
78
+
79
+ it "can contain default values for parameters" do
80
+ subject.router.should_receive(:add_route) do |*args|
81
+ args[0].should respond_to(:call)
82
+ args[1][:path_info].should == %r{^/pattern$}
83
+ args[2].should == {
84
+ :module => :dispatch,
85
+ :controller => :foo,
86
+ :action => :bar,
87
+ :key => :value
88
+ }
89
+ args[3].should == :myroute
90
+ end
91
+ subject.route :myroute, "/pattern" => "#bar", :key => :value, :controller => :foo
92
+ end
93
+
94
+ it "whose contained default values won't override the target-action" do
95
+ subject.router.should_receive(:add_route) do |*args|
96
+ args[0].should respond_to(:call)
97
+ args[1][:path_info].should be_a(Regexp)
98
+ args[2].should == {
99
+ :module => :dispatch,
100
+ :controller => :foo,
101
+ :action => :bar
102
+ }
103
+ args[3].should == :myroute
104
+ end
105
+ subject.route :myroute, "/pattern" => "foo#bar", :action => :baz
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#route's route-pattern" do
111
+ before { Pakada.boot }
112
+
113
+ subject { Pakada[:dispatch] }
114
+
115
+ it "can contain :normal parameters" do
116
+ subject.router.should_receive(:add_route) do |*args|
117
+ args[1][:path_info].should == %r{^/(?<key>[a-z0-9\-_]+)/(?<key2>[a-z0-9\-_]+)$}
118
+ end
119
+ subject.route :myroute, "/:key/:key2" => ""
120
+ end
121
+
122
+ it "can contain *splat parameters" do
123
+ subject.router.should_receive(:add_route) do |*args|
124
+ args[1][:path_info].should == %r{^/(?<key>([a-z0-9\-_]/?)*)$}
125
+ end
126
+ subject.route :myroute, "/*key" => ""
127
+ end
128
+
129
+ it "can contain optional parts" do
130
+ subject.router.should_receive(:add_route) do |*args|
131
+ args[1][:path_info].should == %r{^(/(?<key>[a-z0-9\-_]+))?/(?<key2>[a-z0-9\-_]+)$}
132
+ end
133
+ subject.route :myroute, "(/:key)/:key2" => ""
134
+ end
135
+ end
136
+
137
+ describe "#route's target-action" do
138
+ before { Pakada.boot }
139
+
140
+ subject { Pakada[:dispatch] }
141
+
142
+ it "uses the current module's name as default :module parameter" do
143
+ subject.router.should_receive :add_route do |*args|
144
+ args[2].should == {
145
+ :module => :dispatch
146
+ }
147
+ end
148
+ subject.route "/" => ""
149
+ end
150
+
151
+ it "can consist of a controller and an action" do
152
+ subject.router.should_receive :add_route do |*args|
153
+ args[2].should == {
154
+ :module => :dispatch,
155
+ :controller => :foo,
156
+ :action => :bar
157
+ }
158
+ end
159
+ subject.route "/" => "foo#bar"
160
+ end
161
+
162
+ it "can consist of an action" do
163
+ subject.router.should_receive :add_route do |*args|
164
+ args[2].should == {
165
+ :module => :dispatch,
166
+ :action => :bar
167
+ }
168
+ end
169
+ subject.route "/" => "#bar"
170
+ end
171
+
172
+ it "can consist of a controller" do
173
+ subject.router.should_receive :add_route do |*args|
174
+ args[2].should == {
175
+ :module => :dispatch,
176
+ :controller => :foo
177
+ }
178
+ end
179
+ subject.route "/" => "foo"
180
+ end
181
+
182
+ it "can consist of a module" do
183
+ subject.router.should_receive :add_route do |*args|
184
+ args[2].should == {
185
+ :module => :mymodule,
186
+ }
187
+ end
188
+ subject.route "/" => "mymodule::"
189
+ end
190
+
191
+ it "can consist of a module and a controller" do
192
+ subject.router.should_receive :add_route do |*args|
193
+ args[2].should == {
194
+ :module => :mymodule,
195
+ :controller => :foo
196
+ }
197
+ end
198
+ subject.route "/" => "mymodule::foo"
199
+ end
200
+
201
+ it "can consist of a module and an action" do
202
+ subject.router.should_receive :add_route do |*args|
203
+ args[2].should == {
204
+ :module => :mymodule,
205
+ :action => :bar
206
+ }
207
+ end
208
+ subject.route "/" => "mymodule::#bar"
209
+ end
210
+ end
211
+
212
+ describe "#route's Rack end-point" do
213
+ def stub_action(route, params = {}, route_name = nil, &block)
214
+ params = {
215
+ :module => subject.module_name,
216
+ :controller => :bar,
217
+ :action => :baz
218
+ }.merge(params)
219
+
220
+ controller, action = double("controller"), double("action")
221
+ subject.controllers[:bar] = controller
222
+ controller.should_receive(:action).with(:baz).and_return(action)
223
+ action.should_receive(:call) {|env| block.call env }
224
+
225
+ subject.router.should_receive :add_route do |app, *nothing|
226
+ app.call "rack.routing_args" => params
227
+ end
228
+ subject.route route_name, route => ""
229
+ end
230
+
231
+ before { Pakada.boot }
232
+
233
+ subject { Pakada[:dispatch] }
234
+
235
+ it "splits splat parameters" do
236
+ stub_action "/*something", :something => "/some///thing/123" do |env|
237
+ env["pakada.dispatch.params"][:something].should == ["some", "thing", "123"]
238
+ end
239
+ end
240
+
241
+ it "makes sure the module, controller and action params are symbols" do
242
+ stub_action "/", {
243
+ :module => subject.module_name.to_s,
244
+ :controller => "bar",
245
+ :action => "baz"
246
+ } do |env|
247
+ [:module, :controller, :action].each do |k|
248
+ env["pakada.dispatch.params"][k].should be_kind_of(Symbol)
249
+ end
250
+ end
251
+ end
252
+
253
+ it "calls the respective action" do
254
+ called = false
255
+ stub_action("/") {|env| called = true }
256
+
257
+ called.should be_true
258
+ end
259
+
260
+ it "returns an X-Cascade: pass response if the module or controller doesn't exist" do
261
+ subject.router.should_receive :add_route do |app, *nothing|
262
+ env = {"rack.routing_args" => {
263
+ :module => :dispatch,
264
+ :controller => :bar,
265
+ :action => :foofoofoo
266
+ }}
267
+ app.call(env).should == [404, {"X-Cascade" => "pass"}, []]
268
+ end
269
+ subject.route "/" => ""
270
+ end
271
+
272
+ it "puts the matched route's name into the environment if it has a name" do
273
+ stub_action "/with_name", {}, :myroute do |env|
274
+ env["pakada.dispatch.route"].should == :myroute
275
+ end
276
+
277
+ stub_action "/without_name" do |env|
278
+ env["pakada.dispatch.route"].should be_nil
279
+ end
280
+ end
281
+ end
282
+
283
+ describe "#uri" do
284
+ before { Pakada.boot }
285
+
286
+ subject { Pakada[:dispatch] }
287
+
288
+ it "passes over to #router.url" do
289
+ subject.route :myroute, "/:key" => "foo#bar", :key => "value"
290
+
291
+ subject.router.should_receive(:url).with({}, :myroute, :key => "value2").and_return("/value2")
292
+ subject.url(:myroute, :key => "value2").should == "/value2"
293
+
294
+ subject.router.should_receive(:url).with({}).and_return("/")
295
+ subject.url.should == "/"
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,14 @@
1
+ require "bundler"
2
+ Bundler.setup :default, :development
3
+
4
+ require "pakada/dispatch"
5
+
6
+ require "fakefs/safe"
7
+
8
+ begin
9
+ require "awesome_print"
10
+ rescue LoadError; end
11
+
12
+ RSpec.configure do |config|
13
+ config.before(:each) { Pakada.reset_instance }
14
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pakada-dispatch
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Lars Gierth
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-25 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: pakada
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ prerelease: false
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: rack-mount
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
42
+ version: "0"
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: fakefs
61
+ requirement: &id004 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ type: :development
70
+ prerelease: false
71
+ version_requirements: *id004
72
+ description:
73
+ email:
74
+ - lars.gierth@gmail.com
75
+ executables: []
76
+
77
+ extensions: []
78
+
79
+ extra_rdoc_files: []
80
+
81
+ files:
82
+ - .project
83
+ - .rspec
84
+ - Gemfile
85
+ - LICENSE
86
+ - README.md
87
+ - Rakefile
88
+ - lib/pakada-dispatch.rb
89
+ - lib/pakada/dispatch.rb
90
+ - lib/pakada/dispatch/controller.rb
91
+ - lib/pakada/dispatch/module.rb
92
+ - lib/pakada/dispatch/version.rb
93
+ - pakada-dispatch.gemspec
94
+ - spec/controller_spec.rb
95
+ - spec/dispatch_spec.rb
96
+ - spec/module_spec.rb
97
+ - spec/spec_helper.rb
98
+ has_rdoc: true
99
+ homepage: https://rubygems.org/gems/pakada-dispatch
100
+ licenses: []
101
+
102
+ post_install_message:
103
+ rdoc_options: []
104
+
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ hash: -75253869
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: -75253869
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ requirements: []
126
+
127
+ rubyforge_project:
128
+ rubygems_version: 1.3.7
129
+ signing_key:
130
+ specification_version: 3
131
+ summary: Routing And Action Controllers For Pakada
132
+ test_files: []
133
+