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