pakada-dispatch 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+