deas 0.0.2 → 0.1.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.
- data/deas.gemspec +7 -1
- data/lib/deas/logger.rb +23 -0
- data/lib/deas/route.rb +45 -0
- data/lib/deas/runner.rb +30 -0
- data/lib/deas/server.rb +152 -0
- data/lib/deas/sinatra_app.rb +54 -0
- data/lib/deas/sinatra_runner.rb +119 -0
- data/lib/deas/template.rb +80 -0
- data/lib/deas/test_helpers.rb +15 -0
- data/lib/deas/test_runner.rb +40 -0
- data/lib/deas/version.rb +1 -1
- data/lib/deas/view_handler.rb +97 -0
- data/lib/deas.rb +35 -2
- data/test/helper.rb +9 -1
- data/test/support/fake_app.rb +46 -0
- data/test/support/routes.rb +117 -0
- data/test/support/view_handlers.rb +52 -0
- data/test/support/views/_info.erb +1 -0
- data/test/support/views/layout1.erb +2 -0
- data/test/support/views/layout2.erb +2 -0
- data/test/support/views/layout3.erb +2 -0
- data/test/support/views/show.erb +2 -0
- data/test/support/views/with_layout.erb +1 -0
- data/test/system/making_requests_tests.rb +78 -0
- data/test/unit/deas_tests.rb +21 -0
- data/test/unit/logger_tests.rb +33 -0
- data/test/unit/route_tests.rb +43 -0
- data/test/unit/runner_tests.rb +34 -0
- data/test/unit/server_tests.rb +203 -0
- data/test/unit/sinatra_app_tests.rb +70 -0
- data/test/unit/sinatra_runner_tests.rb +103 -0
- data/test/unit/template_tests.rb +150 -0
- data/test/unit/view_handler_tests.rb +96 -0
- metadata +130 -7
data/deas.gemspec
CHANGED
@@ -17,6 +17,12 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.
|
20
|
+
gem.add_dependency("ns-options", ["~> 1.0"])
|
21
|
+
gem.add_dependency("rack", ["~> 1.5"])
|
22
|
+
gem.add_dependency("sinatra", ["~> 1.4"])
|
23
|
+
|
24
|
+
gem.add_development_dependency("assert", ["~> 2.0"])
|
25
|
+
gem.add_development_dependency("assert-mocha", ["~> 1.0"])
|
26
|
+
gem.add_development_dependency("rack-test", ["~> 0.6"])
|
21
27
|
|
22
28
|
end
|
data/lib/deas/logger.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Deas
|
2
|
+
|
3
|
+
class RunnerLogger
|
4
|
+
attr_reader :summary, :verbose
|
5
|
+
|
6
|
+
def initialize(logger, verbose = true)
|
7
|
+
loggers = [ logger, Deas::NullLogger.new ]
|
8
|
+
loggers.reverse! if !verbose
|
9
|
+
@verbose, @summary = loggers
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
class NullLogger
|
15
|
+
require 'logger'
|
16
|
+
|
17
|
+
::Logger::Severity.constants.each do |name|
|
18
|
+
define_method(name.downcase){|*args| } # no-op
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/deas/route.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'deas/sinatra_runner'
|
2
|
+
|
3
|
+
module Deas
|
4
|
+
|
5
|
+
class Route
|
6
|
+
attr_reader :method, :path, :handler_class_name, :handler_class
|
7
|
+
|
8
|
+
def initialize(method, path, handler_class_name)
|
9
|
+
@method = method
|
10
|
+
@path = path
|
11
|
+
@handler_class_name = handler_class_name
|
12
|
+
@handler_class = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def constantize!
|
16
|
+
@handler_class ||= constantize_name(handler_class_name)
|
17
|
+
raise(NoHandlerClassError.new(handler_class_name)) if !@handler_class
|
18
|
+
end
|
19
|
+
|
20
|
+
def runner(sinatra_call)
|
21
|
+
Deas::SinatraRunner.new(@handler_class, sinatra_call)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def constantize_name(class_name)
|
27
|
+
names = class_name.to_s.split('::').reject{|name| name.empty? }
|
28
|
+
klass = names.inject(Object) do |constant, name|
|
29
|
+
constant.const_get(name)
|
30
|
+
end
|
31
|
+
klass == Object ? false : klass
|
32
|
+
rescue NameError
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
class NoHandlerClassError < RuntimeError
|
39
|
+
def initialize(handler_class_name)
|
40
|
+
super "Deas couldn't find the view handler '#{handler_class_name}'. " \
|
41
|
+
"It doesn't exist or hasn't been required in yet."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/deas/runner.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Deas
|
2
|
+
|
3
|
+
class Runner
|
4
|
+
|
5
|
+
attr_accessor :request, :response, :params, :logger, :session
|
6
|
+
|
7
|
+
def initialize(handler_class)
|
8
|
+
@handler_class = handler_class
|
9
|
+
@handler = @handler_class.new(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def halt(*args)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
|
16
|
+
def render(*args)
|
17
|
+
raise NotImplementedError
|
18
|
+
end
|
19
|
+
|
20
|
+
def redirect(*args)
|
21
|
+
raise NotImplementedError
|
22
|
+
end
|
23
|
+
|
24
|
+
def redirect_to(*args)
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/lib/deas/server.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'ns-options'
|
2
|
+
require 'ns-options/boolean'
|
3
|
+
require 'pathname'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
require 'deas/logger'
|
7
|
+
require 'deas/route'
|
8
|
+
|
9
|
+
module Deas
|
10
|
+
|
11
|
+
class Server
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
class Configuration
|
15
|
+
include NsOptions::Proxy
|
16
|
+
|
17
|
+
# Sinatra based options
|
18
|
+
option :env, String, :default => 'development'
|
19
|
+
option :root, Pathname, :default => proc{ File.dirname(Deas.config.routes_file) }
|
20
|
+
|
21
|
+
option :app_file, Pathname, :default => proc{ Deas.config.routes_file }
|
22
|
+
option :public_folder, Pathname
|
23
|
+
option :views_folder, Pathname
|
24
|
+
|
25
|
+
option :dump_errors, NsOptions::Boolean, :default => false
|
26
|
+
option :method_override, NsOptions::Boolean, :default => true
|
27
|
+
option :sessions, NsOptions::Boolean, :default => true
|
28
|
+
option :show_exceptions, NsOptions::Boolean, :default => false
|
29
|
+
option :static_files, NsOptions::Boolean, :default => true
|
30
|
+
|
31
|
+
# Deas specific options
|
32
|
+
option :init_proc, Proc, :default => proc{ }
|
33
|
+
option :logger, :default => proc{ Deas::NullLogger.new }
|
34
|
+
option :verbose_logging, :default => true
|
35
|
+
|
36
|
+
option :routes, Array, :default => []
|
37
|
+
option :view_handler_ns, String
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
# these are defaulted here because we want to use the Configuration
|
41
|
+
# instance `root`. If we define a proc above, we will be using the
|
42
|
+
# Configuration class `root`, which will not update these options as
|
43
|
+
# expected.
|
44
|
+
super({
|
45
|
+
:public_folder => proc{ self.root.join('public') },
|
46
|
+
:views_folder => proc{ self.root.join('views') }
|
47
|
+
})
|
48
|
+
end
|
49
|
+
|
50
|
+
def runner_logger
|
51
|
+
Deas::RunnerLogger.new(self.logger, self.verbose_logging)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :configuration
|
56
|
+
|
57
|
+
def initialize
|
58
|
+
@configuration = Configuration.new
|
59
|
+
end
|
60
|
+
|
61
|
+
def env(*args)
|
62
|
+
self.configuration.env *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def root(*args)
|
66
|
+
self.configuration.root *args
|
67
|
+
end
|
68
|
+
|
69
|
+
def public_folder(*args)
|
70
|
+
self.configuration.public_folder *args
|
71
|
+
end
|
72
|
+
|
73
|
+
def views_folder(*args)
|
74
|
+
self.configuration.views_folder *args
|
75
|
+
end
|
76
|
+
|
77
|
+
def dump_errors(*args)
|
78
|
+
self.configuration.dump_errors *args
|
79
|
+
end
|
80
|
+
|
81
|
+
def method_override(*args)
|
82
|
+
self.configuration.method_override *args
|
83
|
+
end
|
84
|
+
|
85
|
+
def sessions(*args)
|
86
|
+
self.configuration.sessions *args
|
87
|
+
end
|
88
|
+
|
89
|
+
def show_exceptions(*args)
|
90
|
+
self.configuration.show_exceptions *args
|
91
|
+
end
|
92
|
+
|
93
|
+
def static_files(*args)
|
94
|
+
self.configuration.static_files *args
|
95
|
+
end
|
96
|
+
|
97
|
+
def init(&block)
|
98
|
+
self.configuration.init_proc = block
|
99
|
+
end
|
100
|
+
|
101
|
+
def logger(*args)
|
102
|
+
self.configuration.logger *args
|
103
|
+
end
|
104
|
+
|
105
|
+
def verbose_logging(*args)
|
106
|
+
self.configuration.verbose_logging *args
|
107
|
+
end
|
108
|
+
|
109
|
+
def view_handler_ns(*args)
|
110
|
+
self.configuration.view_handler_ns *args
|
111
|
+
end
|
112
|
+
|
113
|
+
def get(path, handler_class_name)
|
114
|
+
self.route(:get, path, handler_class_name)
|
115
|
+
end
|
116
|
+
|
117
|
+
def post(path, handler_class_name)
|
118
|
+
self.route(:post, path, handler_class_name)
|
119
|
+
end
|
120
|
+
|
121
|
+
def put(path, handler_class_name)
|
122
|
+
self.route(:put, path, handler_class_name)
|
123
|
+
end
|
124
|
+
|
125
|
+
def patch(path, handler_class_name)
|
126
|
+
self.route(:patch, path, handler_class_name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def delete(path, handler_class_name)
|
130
|
+
self.route(:delete, path, handler_class_name)
|
131
|
+
end
|
132
|
+
|
133
|
+
def route(http_method, path, handler_class_name)
|
134
|
+
if self.view_handler_ns && !(handler_class_name =~ /^::/)
|
135
|
+
handler_class_name = "#{self.view_handler_ns}::#{handler_class_name}"
|
136
|
+
end
|
137
|
+
Deas::Route.new(http_method, path, handler_class_name).tap do |route|
|
138
|
+
self.configuration.routes.push(route)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.method_missing(method, *args, &block)
|
143
|
+
self.instance.send(method, *args, &block)
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.respond_to?(*args)
|
147
|
+
super || self.instance.respond_to?(*args)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Deas
|
4
|
+
|
5
|
+
module SinatraApp
|
6
|
+
|
7
|
+
def self.new(server_config)
|
8
|
+
server_config.init_proc.call
|
9
|
+
server_config.routes.each(&:constantize!)
|
10
|
+
|
11
|
+
Class.new(Sinatra::Base).tap do |app|
|
12
|
+
|
13
|
+
# built-in settings
|
14
|
+
app.set :environment, server_config.env
|
15
|
+
app.set :root, server_config.root
|
16
|
+
|
17
|
+
app.set :app_file, server_config.app_file
|
18
|
+
app.set :public_folder, server_config.public_folder
|
19
|
+
app.set :views, server_config.views_folder
|
20
|
+
|
21
|
+
app.set :dump_errors, server_config.dump_errors
|
22
|
+
app.set :logging, false
|
23
|
+
app.set :method_override, server_config.method_override
|
24
|
+
app.set :sessions, server_config.sessions
|
25
|
+
app.set :show_exceptions, server_config.show_exceptions
|
26
|
+
app.set :static, server_config.static_files
|
27
|
+
|
28
|
+
# custom settings
|
29
|
+
app.set :logger, server_config.logger
|
30
|
+
app.set :runner_logger, server_config.runner_logger
|
31
|
+
|
32
|
+
# routes
|
33
|
+
server_config.routes.each do |route|
|
34
|
+
# defines Sinatra routes like:
|
35
|
+
# before('/'){ ... }
|
36
|
+
# get('/'){ ... }
|
37
|
+
# after('/'){ ... }
|
38
|
+
app.before(route.path) do
|
39
|
+
@runner = route.runner(self).setup
|
40
|
+
end
|
41
|
+
app.send(route.method, route.path) do
|
42
|
+
@runner.run
|
43
|
+
end
|
44
|
+
app.after(route.path) do
|
45
|
+
@runner.teardown
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'deas/runner'
|
2
|
+
require 'deas/template'
|
3
|
+
|
4
|
+
module Deas
|
5
|
+
|
6
|
+
class SinatraRunner < Runner
|
7
|
+
|
8
|
+
def initialize(handler_class, sinatra_call)
|
9
|
+
@sinatra_call = sinatra_call
|
10
|
+
@handler_class = handler_class
|
11
|
+
@logger = @sinatra_call.settings.logger
|
12
|
+
@runner_logger = @sinatra_call.settings.runner_logger
|
13
|
+
@params = @sinatra_call.params
|
14
|
+
@request = @sinatra_call.request
|
15
|
+
@response = @sinatra_call.response
|
16
|
+
@session = @sinatra_call.session
|
17
|
+
@time_taken = nil
|
18
|
+
@started_at = nil
|
19
|
+
super(handler_class)
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup
|
23
|
+
@started_at = Time.now
|
24
|
+
log_verbose "===== Received request ====="
|
25
|
+
log_verbose " Method: #{@request.request_method.inspect}"
|
26
|
+
log_verbose " Path: #{@request.path.inspect}"
|
27
|
+
log_verbose " Params: #{@sinatra_call.params.inspect}"
|
28
|
+
log_verbose " Handler: #{@handler_class}"
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
run_callbacks @handler_class.before_callbacks
|
34
|
+
@handler.init
|
35
|
+
response_data = @handler.run
|
36
|
+
run_callbacks @handler_class.after_callbacks
|
37
|
+
response_data
|
38
|
+
end
|
39
|
+
|
40
|
+
# expects that `setup` has been run; this method is dependent on it
|
41
|
+
CODE_NAMES = {
|
42
|
+
200 => 'OK',
|
43
|
+
400 => 'BAD REQUEST' ,
|
44
|
+
401 => 'UNAUTHORIZED',
|
45
|
+
403 => 'FORBIDDEN',
|
46
|
+
404 => 'NOT FOUND',
|
47
|
+
408 => 'TIMEOUT',
|
48
|
+
500 => 'ERROR'
|
49
|
+
}
|
50
|
+
def teardown
|
51
|
+
@time_taken = RoundedTime.new(Time.now - @started_at)
|
52
|
+
@response.status.tap do |code|
|
53
|
+
response_display = [ code, CODE_NAMES[code.to_i] ].compact.join(', ')
|
54
|
+
log_verbose "===== Completed in #{@time_taken}ms " \
|
55
|
+
"#{response_display} ====="
|
56
|
+
end
|
57
|
+
log_summary SummaryLine.new({
|
58
|
+
'status' => @response.status,
|
59
|
+
'method' => @request.request_method,
|
60
|
+
'path' => @request.path,
|
61
|
+
'params' => @params,
|
62
|
+
'time' => @time_taken,
|
63
|
+
'handler' => @handler_class
|
64
|
+
})
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
def log_verbose(message, level = :info)
|
69
|
+
@runner_logger.verbose.send(level, "[Deas] #{message}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def log_summary(message, level = :info)
|
73
|
+
@runner_logger.summary.send(level, "[Deas] #{message}")
|
74
|
+
end
|
75
|
+
|
76
|
+
# Helpers
|
77
|
+
|
78
|
+
def halt(*args)
|
79
|
+
@sinatra_call.halt(*args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def render(name, options = nil, &block)
|
83
|
+
options ||= {}
|
84
|
+
options[:locals] = { :view => @handler }.merge(options[:locals] || {})
|
85
|
+
options[:layout] ||= @handler_class.layouts
|
86
|
+
Deas::Template.new(@sinatra_call, name, options).render(&block)
|
87
|
+
end
|
88
|
+
|
89
|
+
def redirect(*args)
|
90
|
+
@sinatra_call.redirect(*args)
|
91
|
+
end
|
92
|
+
|
93
|
+
def redirect_to(path, *args)
|
94
|
+
@sinatra_call.redirect(@sinatra_call.to(path), *args)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def run_callbacks(callbacks)
|
100
|
+
callbacks.each{|proc| @handler.instance_eval(&proc) }
|
101
|
+
end
|
102
|
+
|
103
|
+
module RoundedTime
|
104
|
+
ROUND_PRECISION = 2
|
105
|
+
ROUND_MODIFIER = 10 ** ROUND_PRECISION
|
106
|
+
def self.new(time_in_seconds)
|
107
|
+
(time_in_seconds * 1000 * ROUND_MODIFIER).to_i / ROUND_MODIFIER.to_f
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
module SummaryLine
|
112
|
+
def self.new(line_attrs)
|
113
|
+
attr_keys = %w{time status handler method path params}
|
114
|
+
attr_keys.map{ |k| "#{k}=#{line_attrs[k].inspect}" }.join(' ')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module Deas
|
4
|
+
|
5
|
+
class Template
|
6
|
+
|
7
|
+
def self.helpers(*helper_modules)
|
8
|
+
Deas::Template::RenderScope.class_eval{ include *helper_modules }
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :name, :options
|
12
|
+
|
13
|
+
def initialize(sinatra_call, name, options = nil)
|
14
|
+
@options = options || {}
|
15
|
+
@options[:scope] = RenderScope.new(sinatra_call)
|
16
|
+
|
17
|
+
@sinatra_call = sinatra_call
|
18
|
+
@name = name.to_sym
|
19
|
+
(@options.delete(:layout) || @options.delete(:layouts) || []).tap do |l|
|
20
|
+
@layouts = l.compact.map(&:to_sym)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# builds Sinatra render-blocks like:
|
25
|
+
#
|
26
|
+
# erb :main_layout do
|
27
|
+
# erb :second_layout do
|
28
|
+
# erb :user_index
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
def render(&block)
|
33
|
+
template_names = [ @layouts, @name ].flatten.reverse
|
34
|
+
top_render_proc = template_names.inject(block) do |render_proc, name|
|
35
|
+
proc{ @sinatra_call.erb(name, @options, &render_proc) }
|
36
|
+
end
|
37
|
+
top_render_proc.call
|
38
|
+
end
|
39
|
+
|
40
|
+
class RenderScope
|
41
|
+
def initialize(sinatra_call)
|
42
|
+
@sinatra_call = sinatra_call
|
43
|
+
end
|
44
|
+
|
45
|
+
def render(name, options = nil, &block)
|
46
|
+
Deas::Template.new(@sinatra_call, name, options || {}).render(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def partial(name, locals = nil)
|
50
|
+
Deas::Partial.new(@sinatra_call, name, locals || {}).render
|
51
|
+
end
|
52
|
+
|
53
|
+
def escape_html(html)
|
54
|
+
Rack::Utils.escape_html(html)
|
55
|
+
end
|
56
|
+
alias :h :escape_html
|
57
|
+
|
58
|
+
def escape_url(path)
|
59
|
+
Rack::Utils.escape_path(path)
|
60
|
+
end
|
61
|
+
alias :u :escape_url
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
class Partial < Template
|
68
|
+
|
69
|
+
def initialize(sinatra_call, name, locals = nil)
|
70
|
+
options = { :locals => (locals || {}) }
|
71
|
+
name = begin
|
72
|
+
basename = File.basename(name.to_s)
|
73
|
+
name.to_s.sub(/#{basename}\Z/, "_#{basename}")
|
74
|
+
end
|
75
|
+
super sinatra_call, name, options
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'deas/logger'
|
2
|
+
require 'deas/runner'
|
3
|
+
|
4
|
+
module Deas
|
5
|
+
|
6
|
+
class TestRunner < Runner
|
7
|
+
|
8
|
+
attr_reader :handler, :return_value
|
9
|
+
|
10
|
+
def initialize(handler_class, args = nil)
|
11
|
+
args = (args || {}).dup
|
12
|
+
@logger = args.delete(:logger) || Deas::NullLogger.new
|
13
|
+
@params = args.delete(:params) || {}
|
14
|
+
@request = args.delete(:request)
|
15
|
+
@response = args.delete(:response)
|
16
|
+
@session = args.delete(:session)
|
17
|
+
|
18
|
+
super(handler_class)
|
19
|
+
args.each{|key, value| @handler.send("#{key}=", value) }
|
20
|
+
|
21
|
+
@return_value = catch(:halt){ @handler.init; nil }
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
@return_value ||= catch(:halt){ @handler.run }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Helpers
|
29
|
+
|
30
|
+
def halt(*args)
|
31
|
+
throw(:halt, args)
|
32
|
+
end
|
33
|
+
|
34
|
+
def render(*args)
|
35
|
+
"test runner render"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/deas/version.rb
CHANGED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'deas/runner'
|
2
|
+
|
3
|
+
module Deas
|
4
|
+
|
5
|
+
module ViewHandler
|
6
|
+
|
7
|
+
def self.included(klass)
|
8
|
+
klass.class_eval do
|
9
|
+
extend ClassMethods
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(runner)
|
14
|
+
@deas_runner = runner
|
15
|
+
end
|
16
|
+
|
17
|
+
def init
|
18
|
+
self.run_callback 'before_init'
|
19
|
+
self.init!
|
20
|
+
self.run_callback 'after_init'
|
21
|
+
end
|
22
|
+
|
23
|
+
def init!
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
self.run_callback 'before_run'
|
28
|
+
data = self.run!
|
29
|
+
self.run_callback 'after_run'
|
30
|
+
data
|
31
|
+
end
|
32
|
+
|
33
|
+
def run!
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
def inspect
|
38
|
+
reference = '0x0%x' % (self.object_id << 1)
|
39
|
+
"#<#{self.class}:#{reference} @request=#{self.request.inspect}>"
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def before_init; end
|
45
|
+
def after_init; end
|
46
|
+
def before_run; end
|
47
|
+
def after_run; end
|
48
|
+
|
49
|
+
# Helpers
|
50
|
+
|
51
|
+
def halt(*args); @deas_runner.halt(*args); end
|
52
|
+
def redirect(*args); @deas_runner.redirect(*args); end
|
53
|
+
def redirect_to(*args); @deas_runner.redirect_to(*args); end
|
54
|
+
|
55
|
+
def render(*args, &block)
|
56
|
+
@deas_runner.render(*args, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def logger; @deas_runner.logger; end
|
60
|
+
def request; @deas_runner.request; end
|
61
|
+
def response; @deas_runner.response; end
|
62
|
+
def params; @deas_runner.params; end
|
63
|
+
def session; @deas_runner.session; end
|
64
|
+
|
65
|
+
def run_callback(callback)
|
66
|
+
self.send(callback.to_s)
|
67
|
+
end
|
68
|
+
|
69
|
+
module ClassMethods
|
70
|
+
|
71
|
+
def before(&block)
|
72
|
+
self.before_callbacks << block
|
73
|
+
end
|
74
|
+
|
75
|
+
def before_callbacks
|
76
|
+
@before_callbacks ||= []
|
77
|
+
end
|
78
|
+
|
79
|
+
def after(&block)
|
80
|
+
self.after_callbacks << block
|
81
|
+
end
|
82
|
+
|
83
|
+
def after_callbacks
|
84
|
+
@after_callbacks ||= []
|
85
|
+
end
|
86
|
+
|
87
|
+
def layout(*args)
|
88
|
+
@layouts = args unless args.empty?
|
89
|
+
@layouts
|
90
|
+
end
|
91
|
+
alias :layouts :layout
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|