deas 0.31.0 → 0.32.0
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.
- checksums.yaml +7 -0
- data/Gemfile +1 -1
- data/lib/deas/exceptions.rb +2 -0
- data/lib/deas/handler_proxy.rb +41 -0
- data/lib/deas/redirect_proxy.rb +2 -1
- data/lib/deas/route.rb +13 -23
- data/lib/deas/route_proxy.rb +12 -7
- data/lib/deas/router.rb +70 -14
- data/lib/deas/server.rb +4 -0
- data/lib/deas/version.rb +1 -1
- data/test/support/routes.rb +22 -0
- data/test/system/rack_tests.rb +16 -4
- data/test/unit/exceptions_tests.rb +8 -3
- data/test/unit/handler_proxy_tests.rb +115 -0
- data/test/unit/redirect_proxy_tests.rb +7 -7
- data/test/unit/route_proxy_tests.rb +22 -4
- data/test/unit/route_tests.rb +34 -75
- data/test/unit/router_tests.rb +215 -88
- data/test/unit/server_configuration_tests.rb +5 -7
- data/test/unit/server_tests.rb +5 -4
- data/test/unit/sinatra_app_tests.rb +2 -3
- metadata +89 -111
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e01bef9b6af4303f73139d7163cffe10e365422
|
4
|
+
data.tar.gz: 72a8a94d809478d18b0977d6f08db810a4801547
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d911b586a2a5550d68b1213da0928c9660bded2411454543f838d5aa882652412d7bc3717c526fd9b53349c5250ce37c66c0feffb5105e8c65ea7382bb0ebf9a
|
7
|
+
data.tar.gz: 29061f4db02882144065819d5f86c720cf9859eb100972f88c070ce23c90257b65bf8f52a0cc6c973f3c94b2a6c7746656aa20613916d2be4a2049526ce321da
|
data/Gemfile
CHANGED
data/lib/deas/exceptions.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'deas/exceptions'
|
2
|
+
require 'deas/sinatra_runner'
|
3
|
+
|
4
|
+
module Deas
|
5
|
+
|
6
|
+
class HandlerProxy
|
7
|
+
|
8
|
+
attr_reader :handler_class_name, :handler_class
|
9
|
+
|
10
|
+
def initialize(handler_class_name)
|
11
|
+
@handler_class_name = handler_class_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate!
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(sinatra_call)
|
19
|
+
runner = SinatraRunner.new(self.handler_class, {
|
20
|
+
:sinatra_call => sinatra_call,
|
21
|
+
:request => sinatra_call.request,
|
22
|
+
:response => sinatra_call.response,
|
23
|
+
:session => sinatra_call.session,
|
24
|
+
:params => sinatra_call.params,
|
25
|
+
:logger => sinatra_call.settings.logger,
|
26
|
+
:router => sinatra_call.settings.router,
|
27
|
+
:template_source => sinatra_call.settings.template_source
|
28
|
+
})
|
29
|
+
|
30
|
+
sinatra_call.request.env.tap do |env|
|
31
|
+
env['deas.params'] = runner.params
|
32
|
+
env['deas.handler_class_name'] = self.handler_class.name
|
33
|
+
env['deas.logging'].call " Handler: #{env['deas.handler_class_name']}"
|
34
|
+
env['deas.logging'].call " Params: #{env['deas.params'].inspect}"
|
35
|
+
end
|
36
|
+
runner.run
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/lib/deas/redirect_proxy.rb
CHANGED
data/lib/deas/route.rb
CHANGED
@@ -1,39 +1,29 @@
|
|
1
|
-
require 'deas/
|
1
|
+
require 'deas/exceptions'
|
2
2
|
|
3
3
|
module Deas
|
4
4
|
|
5
5
|
class Route
|
6
6
|
|
7
|
-
attr_reader :method, :path, :
|
7
|
+
attr_reader :method, :path, :handler_proxies
|
8
8
|
|
9
|
-
def initialize(method, path,
|
10
|
-
@method, @path, @
|
9
|
+
def initialize(method, path, handler_proxies)
|
10
|
+
@method, @path, @handler_proxies = method, path, handler_proxies
|
11
11
|
end
|
12
12
|
|
13
13
|
def validate!
|
14
|
-
@
|
15
|
-
|
14
|
+
@handler_proxies.each do |request_type_name, proxy|
|
15
|
+
proxy.validate!
|
16
|
+
end
|
16
17
|
end
|
17
18
|
|
18
19
|
def run(sinatra_call)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
:params => sinatra_call.params,
|
25
|
-
:logger => sinatra_call.settings.logger,
|
26
|
-
:router => sinatra_call.settings.router,
|
27
|
-
:template_source => sinatra_call.settings.template_source
|
28
|
-
})
|
29
|
-
|
30
|
-
sinatra_call.request.env.tap do |env|
|
31
|
-
env['deas.params'] = runner.params
|
32
|
-
env['deas.handler_class_name'] = self.handler_class.name
|
33
|
-
env['deas.logging'].call " Handler: #{env['deas.handler_class_name']}"
|
34
|
-
env['deas.logging'].call " Params: #{env['deas.params'].inspect}"
|
20
|
+
type = sinatra_call.settings.router.request_type_name(sinatra_call.request)
|
21
|
+
proxy = begin
|
22
|
+
@handler_proxies[type]
|
23
|
+
rescue HandlerProxyNotFound
|
24
|
+
sinatra_call.halt(404)
|
35
25
|
end
|
36
|
-
|
26
|
+
proxy.run(sinatra_call)
|
37
27
|
end
|
38
28
|
|
39
29
|
end
|
data/lib/deas/route_proxy.rb
CHANGED
@@ -1,18 +1,22 @@
|
|
1
1
|
require 'deas/exceptions'
|
2
|
-
require 'deas/
|
2
|
+
require 'deas/handler_proxy'
|
3
3
|
|
4
4
|
module Deas
|
5
|
-
class RouteProxy
|
6
5
|
|
7
|
-
|
6
|
+
class RouteProxy < HandlerProxy
|
8
7
|
|
9
|
-
def initialize(handler_class_name)
|
10
|
-
|
8
|
+
def initialize(handler_class_name, view_handler_ns = nil)
|
9
|
+
raise(NoHandlerClassError.new(handler_class_name)) if handler_class_name.nil?
|
10
|
+
|
11
|
+
if view_handler_ns && !(handler_class_name =~ /^::/)
|
12
|
+
handler_class_name = "#{view_handler_ns}::#{handler_class_name}"
|
13
|
+
end
|
14
|
+
super(handler_class_name)
|
11
15
|
end
|
12
16
|
|
13
17
|
def validate!
|
14
|
-
@handler_class = constantize(
|
15
|
-
raise(NoHandlerClassError.new(
|
18
|
+
@handler_class = constantize(self.handler_class_name).tap do |handler_class|
|
19
|
+
raise(NoHandlerClassError.new(self.handler_class_name)) if !handler_class
|
16
20
|
end
|
17
21
|
end
|
18
22
|
|
@@ -27,4 +31,5 @@ module Deas
|
|
27
31
|
end
|
28
32
|
|
29
33
|
end
|
34
|
+
|
30
35
|
end
|
data/lib/deas/router.rb
CHANGED
@@ -1,15 +1,21 @@
|
|
1
|
+
require 'deas/exceptions'
|
1
2
|
require 'deas/redirect_proxy'
|
2
3
|
require 'deas/route'
|
3
4
|
require 'deas/route_proxy'
|
4
5
|
require 'deas/url'
|
5
6
|
|
6
7
|
module Deas
|
8
|
+
|
7
9
|
class Router
|
8
10
|
|
9
|
-
|
11
|
+
DEFAULT_REQUEST_TYPE_NAME = 'default'
|
12
|
+
|
13
|
+
attr_reader :request_types, :urls, :routes
|
10
14
|
|
11
15
|
def initialize(&block)
|
16
|
+
@request_types = []
|
12
17
|
@urls, @routes = {}, []
|
18
|
+
default_request_type_name(DEFAULT_REQUEST_TYPE_NAME)
|
13
19
|
self.instance_eval(&block) if !block.nil?
|
14
20
|
end
|
15
21
|
|
@@ -41,21 +47,42 @@ module Deas
|
|
41
47
|
prepend_base_url(url.path_for(*args))
|
42
48
|
end
|
43
49
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
def default_request_type_name(value = nil)
|
51
|
+
@default_request_type = RequestType.new(value) if !value.nil?
|
52
|
+
@default_request_type.name
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_request_type(name, &proc)
|
56
|
+
@request_types << RequestType.new(name, proc)
|
57
|
+
end
|
58
|
+
|
59
|
+
# ideally someday the request should just *know* its request type
|
60
|
+
def request_type_name(request)
|
61
|
+
(self.request_types.detect{ |rt| rt.proc.call(request) } || @default_request_type).name
|
62
|
+
end
|
49
63
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
64
|
+
def get(path, *args); self.route(:get, path, *args); end
|
65
|
+
def post(path, *args); self.route(:post, path, *args); end
|
66
|
+
def put(path, *args); self.route(:put, path, *args); end
|
67
|
+
def patch(path, *args); self.route(:patch, path, *args); end
|
68
|
+
def delete(path, *args); self.route(:delete, path, *args); end
|
69
|
+
|
70
|
+
def route(http_method, from_path, *args)
|
71
|
+
handler_names = args.last.kind_of?(::Hash) ? args.pop : {}
|
72
|
+
default_handler_name = args.last
|
73
|
+
if !handler_names.key?(self.default_request_type_name) && default_handler_name
|
74
|
+
handler_names[self.default_request_type_name] = default_handler_name
|
75
|
+
end
|
76
|
+
|
77
|
+
proxies = handler_names.inject({}) do |proxies, (req_type_name, handler_name)|
|
78
|
+
proxies[req_type_name] = Deas::RouteProxy.new(handler_name, self.view_handler_ns)
|
79
|
+
proxies
|
53
80
|
end
|
54
|
-
proxy = Deas::RouteProxy.new(handler_class_name)
|
55
81
|
|
56
82
|
from_url = self.urls[from_path]
|
57
83
|
from_url_path = from_url.path if from_url
|
58
|
-
|
84
|
+
|
85
|
+
add_route(http_method, prepend_base_url(from_url_path || from_path), proxies)
|
59
86
|
end
|
60
87
|
|
61
88
|
def redirect(from_path, to_path = nil, &block)
|
@@ -63,11 +90,14 @@ module Deas
|
|
63
90
|
if to_path.kind_of?(::Symbol) && to_url.nil?
|
64
91
|
raise ArgumentError, "no url named `#{to_path.inspect}`"
|
65
92
|
end
|
93
|
+
|
66
94
|
proxy = Deas::RedirectProxy.new(to_url || to_path, &block)
|
95
|
+
proxies = { self.default_request_type_name => proxy }
|
67
96
|
|
68
97
|
from_url = self.urls[from_path]
|
69
98
|
from_url_path = from_url.path if from_url
|
70
|
-
|
99
|
+
|
100
|
+
add_route(:get, prepend_base_url(from_url_path || from_path), proxies)
|
71
101
|
end
|
72
102
|
|
73
103
|
private
|
@@ -76,10 +106,36 @@ module Deas
|
|
76
106
|
self.urls[name] = Deas::Url.new(name, path)
|
77
107
|
end
|
78
108
|
|
79
|
-
def add_route(http_method, path,
|
80
|
-
|
109
|
+
def add_route(http_method, path, proxies)
|
110
|
+
proxies = HandlerProxies.new(proxies, self.default_request_type_name)
|
111
|
+
Deas::Route.new(http_method, path, proxies).tap{ |r| self.routes.push(r) }
|
81
112
|
end
|
82
113
|
|
114
|
+
class HandlerProxies
|
115
|
+
|
116
|
+
attr_reader :default_type
|
117
|
+
|
118
|
+
def initialize(proxies, default_name)
|
119
|
+
@proxies = proxies
|
120
|
+
@default_type = default_name
|
121
|
+
end
|
122
|
+
|
123
|
+
def [](type)
|
124
|
+
@proxies[type] || @proxies[@default_type] || raise(HandlerProxyNotFound)
|
125
|
+
end
|
126
|
+
|
127
|
+
def each(&block)
|
128
|
+
@proxies.each(&block)
|
129
|
+
end
|
130
|
+
|
131
|
+
def empty?
|
132
|
+
@proxies.empty?
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
RequestType = Struct.new(:name, :proc)
|
138
|
+
|
83
139
|
end
|
84
140
|
|
85
141
|
end
|
data/lib/deas/server.rb
CHANGED
@@ -211,6 +211,10 @@ module Deas::Server
|
|
211
211
|
def url(*args, &block); self.router.url(*args, &block); end
|
212
212
|
def url_for(*args, &block); self.router.url_for(*args, &block); end
|
213
213
|
|
214
|
+
def default_request_type_name(*args); self.router.default_request_type_name(*args); end
|
215
|
+
def add_request_type(*args, &block); self.router.add_request_type(*args, &block); end
|
216
|
+
def request_type_name(*args); self.router.request_type_name(*args); end
|
217
|
+
|
214
218
|
def get(*args, &block); self.router.get(*args, &block); end
|
215
219
|
def post(*args, &block); self.router.post(*args, &block); end
|
216
220
|
def put(*args, &block); self.router.put(*args, &block); end
|
data/lib/deas/version.rb
CHANGED
data/test/support/routes.rb
CHANGED
@@ -19,6 +19,10 @@ class DeasTestServer
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
default_request_type_name 'desktop'
|
23
|
+
add_request_type('regular'){ |r| r.path_info =~ /regular/ }
|
24
|
+
add_request_type('mobile'){ |r| r.path_info =~ /mobile/ }
|
25
|
+
|
22
26
|
get '/show', 'ShowHandler'
|
23
27
|
get '/show.html', 'ShowHtmlHandler'
|
24
28
|
get '/show.json', 'ShowJsonHandler'
|
@@ -26,6 +30,9 @@ class DeasTestServer
|
|
26
30
|
get '/show-text', 'ShowTextHandler'
|
27
31
|
get '/show-headers-text', 'ShowHeadersTextHandler'
|
28
32
|
|
33
|
+
get '/req-type-show/:type', 'regular' => 'ShowHandler',
|
34
|
+
'mobile' => 'ShowMobileHandler'
|
35
|
+
|
29
36
|
get '/halt', 'HaltHandler'
|
30
37
|
get '/error', 'ErrorHandler'
|
31
38
|
get '/redirect', 'RedirectHandler'
|
@@ -71,6 +78,21 @@ class ShowHandler
|
|
71
78
|
|
72
79
|
end
|
73
80
|
|
81
|
+
class ShowMobileHandler
|
82
|
+
include Deas::ViewHandler
|
83
|
+
|
84
|
+
attr_reader :message
|
85
|
+
|
86
|
+
def init!
|
87
|
+
@message = "[MOBILE] #{params['message']}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def run!
|
91
|
+
@message
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
74
96
|
class ShowHtmlHandler
|
75
97
|
include Deas::ViewHandler
|
76
98
|
|
data/test/system/rack_tests.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'assert'
|
2
|
-
require 'assert-rack-test'
|
3
2
|
require 'deas'
|
4
3
|
|
4
|
+
require 'assert-rack-test'
|
5
|
+
|
5
6
|
module Deas
|
6
7
|
|
7
8
|
class RackTestsContext < Assert::Context
|
@@ -20,8 +21,7 @@ module Deas
|
|
20
21
|
get '/show', 'message' => 'this is a test'
|
21
22
|
|
22
23
|
assert_equal 200, last_response.status
|
23
|
-
|
24
|
-
assert_equal exp, last_response.body
|
24
|
+
assert_equal "this is a test", last_response.body
|
25
25
|
end
|
26
26
|
|
27
27
|
should "set the content type appropriately" do
|
@@ -44,6 +44,19 @@ module Deas
|
|
44
44
|
assert_equal 'text/plain', last_response.headers['Content-Type']
|
45
45
|
end
|
46
46
|
|
47
|
+
should "render different handlers for the same meth/path based on the type" do
|
48
|
+
get '/req-type-show/regular', 'message' => 'this is a test request'
|
49
|
+
assert_equal 200, last_response.status
|
50
|
+
assert_equal "this is a test request", last_response.body
|
51
|
+
|
52
|
+
get '/req-type-show/mobile', 'message' => 'this is a test request'
|
53
|
+
assert_equal 200, last_response.status
|
54
|
+
assert_equal "[MOBILE] this is a test request", last_response.body
|
55
|
+
|
56
|
+
get '/req-type-show/other', 'message' => 'this is a test request'
|
57
|
+
assert_equal 404, last_response.status
|
58
|
+
end
|
59
|
+
|
47
60
|
should "allow halting with a custom response" do
|
48
61
|
get '/halt', 'with' => 234
|
49
62
|
|
@@ -115,7 +128,6 @@ module Deas
|
|
115
128
|
desc "handler"
|
116
129
|
setup do
|
117
130
|
get 'handler/tests?a-param=something'
|
118
|
-
|
119
131
|
@data_inspect = last_response.body
|
120
132
|
end
|
121
133
|
|
@@ -11,7 +11,7 @@ module Deas
|
|
11
11
|
assert_kind_of RuntimeError, Deas::Error.new
|
12
12
|
end
|
13
13
|
|
14
|
-
should "provide a no handler class exception
|
14
|
+
should "provide a no handler class exception" do
|
15
15
|
assert Deas::NoHandlerClassError
|
16
16
|
|
17
17
|
handler_class_name = 'AHandlerClass'
|
@@ -23,12 +23,12 @@ module Deas
|
|
23
23
|
assert_equal exp_msg, e.message
|
24
24
|
end
|
25
25
|
|
26
|
-
should "provide a server exception
|
26
|
+
should "provide a server exception" do
|
27
27
|
assert Deas::ServerError
|
28
28
|
assert_kind_of Deas::Error, Deas::ServerError.new
|
29
29
|
end
|
30
30
|
|
31
|
-
should "provide a server root exception
|
31
|
+
should "provide a server root exception" do
|
32
32
|
assert Deas::ServerRootError
|
33
33
|
|
34
34
|
e = Deas::ServerRootError.new
|
@@ -36,6 +36,11 @@ module Deas
|
|
36
36
|
assert_equal "server `root` not set but required", e.message
|
37
37
|
end
|
38
38
|
|
39
|
+
should "provide a handler proxy not found exception" do
|
40
|
+
assert Deas::HandlerProxyNotFound
|
41
|
+
assert_kind_of Deas::Error, Deas::HandlerProxyNotFound.new
|
42
|
+
end
|
43
|
+
|
39
44
|
end
|
40
45
|
|
41
46
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'assert'
|
2
|
+
require 'deas/handler_proxy'
|
3
|
+
|
4
|
+
require 'deas/exceptions'
|
5
|
+
require 'deas/sinatra_runner'
|
6
|
+
require 'test/support/fake_sinatra_call'
|
7
|
+
require 'test/support/view_handlers'
|
8
|
+
|
9
|
+
class Deas::HandlerProxy
|
10
|
+
|
11
|
+
class UnitTests < Assert::Context
|
12
|
+
desc "Deas::HandlerProxy"
|
13
|
+
setup do
|
14
|
+
@proxy = Deas::HandlerProxy.new('EmptyViewHandler')
|
15
|
+
end
|
16
|
+
subject{ @proxy }
|
17
|
+
|
18
|
+
should have_readers :handler_class_name, :handler_class
|
19
|
+
should have_imeths :validate!, :run
|
20
|
+
|
21
|
+
should "know its handler class name" do
|
22
|
+
assert_equal 'EmptyViewHandler', subject.handler_class_name
|
23
|
+
end
|
24
|
+
|
25
|
+
should "not implement its validate! method" do
|
26
|
+
assert_raises(NotImplementedError){ subject.validate! }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
class RunTests < UnitTests
|
32
|
+
desc "when run"
|
33
|
+
setup do
|
34
|
+
@runner_spy = SinatraRunnerSpy.new
|
35
|
+
Assert.stub(Deas::SinatraRunner, :new) do |*args|
|
36
|
+
@runner_spy.build(*args)
|
37
|
+
@runner_spy
|
38
|
+
end
|
39
|
+
|
40
|
+
Assert.stub(@proxy, :handler_class){ EmptyViewHandler }
|
41
|
+
|
42
|
+
@fake_sinatra_call = FakeSinatraCall.new
|
43
|
+
@proxy.run(@fake_sinatra_call)
|
44
|
+
end
|
45
|
+
|
46
|
+
should "build and run a sinatra runner" do
|
47
|
+
assert_equal subject.handler_class, @runner_spy.handler_class
|
48
|
+
|
49
|
+
exp_args = {
|
50
|
+
:sinatra_call => @fake_sinatra_call,
|
51
|
+
:request => @fake_sinatra_call.request,
|
52
|
+
:response => @fake_sinatra_call.response,
|
53
|
+
:session => @fake_sinatra_call.session,
|
54
|
+
:params => @fake_sinatra_call.params,
|
55
|
+
:logger => @fake_sinatra_call.settings.logger,
|
56
|
+
:router => @fake_sinatra_call.settings.router,
|
57
|
+
:template_source => @fake_sinatra_call.settings.template_source
|
58
|
+
}
|
59
|
+
assert_equal exp_args, @runner_spy.args
|
60
|
+
|
61
|
+
assert_true @runner_spy.run_called
|
62
|
+
end
|
63
|
+
|
64
|
+
should "add the runner params to the request env" do
|
65
|
+
exp = @runner_spy.params
|
66
|
+
assert_equal exp, @fake_sinatra_call.request.env['deas.params']
|
67
|
+
end
|
68
|
+
|
69
|
+
should "add the handler class name to the request env" do
|
70
|
+
exp = subject.handler_class.name
|
71
|
+
assert_equal exp, @fake_sinatra_call.request.env['deas.handler_class_name']
|
72
|
+
end
|
73
|
+
|
74
|
+
should "log the handler and params" do
|
75
|
+
exp_msgs = [
|
76
|
+
" Handler: #{subject.handler_class}",
|
77
|
+
" Params: #{@runner_spy.params.inspect}"
|
78
|
+
]
|
79
|
+
assert_equal exp_msgs, @fake_sinatra_call.request.logging_msgs
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
class SinatraRunnerSpy
|
85
|
+
|
86
|
+
attr_reader :run_called
|
87
|
+
attr_reader :handler_class, :args
|
88
|
+
attr_reader :sinatra_call
|
89
|
+
attr_reader :request, :response, :session, :params
|
90
|
+
attr_reader :logger, :router, :template_source
|
91
|
+
|
92
|
+
def initialize
|
93
|
+
@run_called = false
|
94
|
+
end
|
95
|
+
|
96
|
+
def build(handler_class, args)
|
97
|
+
@handler_class, @args = handler_class, args
|
98
|
+
|
99
|
+
@sinatra_call = args[:sinatra_call]
|
100
|
+
@request = args[:request]
|
101
|
+
@response = args[:response]
|
102
|
+
@session = args[:session]
|
103
|
+
@params = args[:params]
|
104
|
+
@logger = args[:logger]
|
105
|
+
@router = args[:router]
|
106
|
+
@template_source = args[:template_source]
|
107
|
+
end
|
108
|
+
|
109
|
+
def run
|
110
|
+
@run_called = true
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|