racket-mvc 0.0.3
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/COPYING.AGPL +661 -0
- data/README.md +40 -0
- data/Rakefile +13 -0
- data/lib/racket.rb +53 -0
- data/lib/racket/application.rb +253 -0
- data/lib/racket/controller.rb +148 -0
- data/lib/racket/current.rb +49 -0
- data/lib/racket/request.rb +32 -0
- data/lib/racket/response.rb +25 -0
- data/lib/racket/router.rb +114 -0
- data/lib/racket/session.rb +37 -0
- data/lib/racket/utils.rb +25 -0
- data/lib/racket/version.rb +33 -0
- data/lib/racket/view_cache.rb +110 -0
- data/spec/_custom.rb +48 -0
- data/spec/_default.rb +175 -0
- data/spec/racket.rb +24 -0
- data/spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb +15 -0
- data/spec/test_custom_app/controllers/sub2/custom_sub_controller_2.rb +32 -0
- data/spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb +13 -0
- data/spec/test_custom_app/controllers/sub3/inherited/custom_inherited_controller.rb +9 -0
- data/spec/test_custom_app/extra/blob.rb +1 -0
- data/spec/test_custom_app/extra/blob/inner_blob.rb +1 -0
- data/spec/test_custom_app/layouts/sub2/zebra.erb +7 -0
- data/spec/test_custom_app/templates/sub2/template.erb +1 -0
- data/spec/test_default_app/controllers/default_root_controller.rb +32 -0
- data/spec/test_default_app/controllers/sub1/default_sub_controller_1.rb +15 -0
- data/spec/test_default_app/controllers/sub2/default_sub_controller_2.rb +15 -0
- data/spec/test_default_app/controllers/sub3/default_sub_controller_3.rb +7 -0
- data/spec/test_default_app/controllers/sub3/inherited/default_inherited_controller.rb +9 -0
- metadata +200 -0
data/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Racket - The noisy Rack MVC framework
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/lasso/racket) [](https://codecov.io/github/lasso/racket?branch=master)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Say what?
|
|
7
|
+
Yes. It is yet another framework built on rack. Using MVC. Doing silly stuff while you look the other way.
|
|
8
|
+
|
|
9
|
+
## Why? I though there were a gazillion frameworks that did the same thing already...
|
|
10
|
+
You are correct. There are _lots_ of Rack frameworks out there. This one does not pretend to do anything special
|
|
11
|
+
that you could not get from any of them.
|
|
12
|
+
|
|
13
|
+
## So, I have to ask again. Why did you create this monstrosity?
|
|
14
|
+
Well, when my web host suddenly started insisting on using Phusion Passenger on all of their servers
|
|
15
|
+
I needed to replace my old [Ramaze](http://ramaze.net/) setup without to much hassle. I tried several
|
|
16
|
+
other Rack framework, but none of them seemed capable of replacing my apps without some major rewrites.
|
|
17
|
+
|
|
18
|
+
## So you just though writing a whole new framework would be easier than using Rails?
|
|
19
|
+
Yes. Writing Rack frameworks is easy! And since I am able to decide exactly what features I want I don't
|
|
20
|
+
need to adopt to a large ecosystem of concepts I do not like.
|
|
21
|
+
|
|
22
|
+
## So, is it any good?
|
|
23
|
+
Probably not. At the moment it is good _enough_ for my needs, but I plan to add more features/make stuff faster
|
|
24
|
+
as I start porting more of my old apps from Ramaze.
|
|
25
|
+
|
|
26
|
+
## Where are the tests?
|
|
27
|
+
Have a look in the `spec` directory. The code base have tests covering 100 per cent of the code and I am planning on keeping it that way. At the moment the code is tested using ruby 2.0, ruby 2.1.6 and 2.2.2, but more versions might be added later.
|
|
28
|
+
|
|
29
|
+
I am using [bacon](https://github.com/chneukirchen/bacon) and [rack-test](https://github.com/brynary/rack-test) for testing. Run the tests by typing `bacon spec/racket.rb`in the root directory. Code coverage reports are provided by [simplecov](https://rubygems.org/gems/simplecov). After the tests have run the an HTML report can be found in the `coverage` directory. If you are not interested in running the tests yourself you could also have a look at the test status at [Travis CI](https://travis-ci.org/lasso/racket) and the code coverage at [Codecov](https://codecov.io/github/lasso/racket). Their stats get updated on every commit.
|
|
30
|
+
|
|
31
|
+
## Alright, I want to try using this stuff. Where are the docs?
|
|
32
|
+
Unfortunately there aren't any docs yet. The main reason is that most things are not finished yet, I am still
|
|
33
|
+
moving stuff around like crazy. There **will** be a wiki later and I also plan on documenting the code itself heavily
|
|
34
|
+
(using [Yard](http://yardoc.org/)).
|
|
35
|
+
|
|
36
|
+
## Why is the code licenced under the GNU Affero General Public License? I want a more liberal licence!
|
|
37
|
+
Because I think it is a Good Thing™ to share code. The
|
|
38
|
+
[GNU Affero General Public License licence](https://www.gnu.org/licenses/agpl.html) is very liberal unless you plan
|
|
39
|
+
on beeing egotistical. I you feel you cannot work with that, please choose
|
|
40
|
+
[something else](https://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#Ruby).
|
data/Rakefile
ADDED
data/lib/racket.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Racket - The noisy Rack MVC framework
|
|
3
|
+
Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
|
|
4
|
+
|
|
5
|
+
This file is part of Racket.
|
|
6
|
+
|
|
7
|
+
Racket is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
Racket is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU Affero General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
along with Racket. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'pathname'
|
|
22
|
+
require 'rack'
|
|
23
|
+
|
|
24
|
+
require_relative 'racket/application.rb'
|
|
25
|
+
require_relative 'racket/controller.rb'
|
|
26
|
+
require_relative 'racket/current.rb'
|
|
27
|
+
require_relative 'racket/request.rb'
|
|
28
|
+
require_relative 'racket/response.rb'
|
|
29
|
+
require_relative 'racket/router.rb'
|
|
30
|
+
require_relative 'racket/session.rb'
|
|
31
|
+
require_relative 'racket/view_cache.rb'
|
|
32
|
+
require_relative 'racket/utils.rb'
|
|
33
|
+
require_relative 'racket/version.rb'
|
|
34
|
+
|
|
35
|
+
module Racket
|
|
36
|
+
# Requires a file using the current application directory as a base path.
|
|
37
|
+
#
|
|
38
|
+
# @param [Object] args
|
|
39
|
+
# @return nil
|
|
40
|
+
def require(*args)
|
|
41
|
+
Application.require(*args)
|
|
42
|
+
nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the current version of Racket.
|
|
46
|
+
#
|
|
47
|
+
# @return [String]
|
|
48
|
+
def version
|
|
49
|
+
Version.current
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
module_function :require, :version
|
|
53
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Racket - The noisy Rack MVC framework
|
|
3
|
+
Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
|
|
4
|
+
|
|
5
|
+
This file is part of Racket.
|
|
6
|
+
|
|
7
|
+
Racket is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
Racket is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU Affero General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
along with Racket. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'logger'
|
|
22
|
+
|
|
23
|
+
module Racket
|
|
24
|
+
# Racket main application class.
|
|
25
|
+
class Application
|
|
26
|
+
|
|
27
|
+
attr_reader :options, :router
|
|
28
|
+
|
|
29
|
+
@current = nil
|
|
30
|
+
|
|
31
|
+
# Called whenever Rack sends a request to the application.
|
|
32
|
+
#
|
|
33
|
+
# @param [Hash] env Rack environment
|
|
34
|
+
# @return [Array] A Rack response array
|
|
35
|
+
def self.call(env)
|
|
36
|
+
@current.call(env)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns a route to the specified controller/action/parameter combination.
|
|
40
|
+
#
|
|
41
|
+
# @param [Class] controller
|
|
42
|
+
# @param [Symbol] action
|
|
43
|
+
# @param [Array] params
|
|
44
|
+
# @return [String]
|
|
45
|
+
def self.get_route(controller, action, params)
|
|
46
|
+
router.get_route(controller, action, params)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Initializes a new Racket::Application object with default options.
|
|
50
|
+
#
|
|
51
|
+
# @return [Class]
|
|
52
|
+
def self.default
|
|
53
|
+
fail 'Application has already been initialized!' if @current
|
|
54
|
+
@current = self.new
|
|
55
|
+
@current.reload
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Sends a message to the logger, but only if the application is running in dev mode.
|
|
60
|
+
#
|
|
61
|
+
# @param [String] message
|
|
62
|
+
# @param [Symbol] level
|
|
63
|
+
# @return nil
|
|
64
|
+
def self.inform_dev(message, level = :info)
|
|
65
|
+
@current.inform(message, level) if options[:mode] == :dev
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Sends a message to the logger.
|
|
70
|
+
#
|
|
71
|
+
# @param [String] message
|
|
72
|
+
# @param [Symbol] level
|
|
73
|
+
# @return nil
|
|
74
|
+
def self.inform_all(message, level = :info)
|
|
75
|
+
@current.inform(message, level)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns options for the currently running Racket::Application.
|
|
79
|
+
#
|
|
80
|
+
# @return [Hash]
|
|
81
|
+
def self.options
|
|
82
|
+
@current.options
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Requires a file using the current application directory as a base path.
|
|
86
|
+
#
|
|
87
|
+
# @param [Object] args
|
|
88
|
+
# @return nil
|
|
89
|
+
def self.require(*args)
|
|
90
|
+
@current.require(*args)
|
|
91
|
+
nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns the router associated with the currenntly running Racket::Application.
|
|
95
|
+
#
|
|
96
|
+
# @return [Racket::Router]
|
|
97
|
+
def self.router
|
|
98
|
+
@current.router
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private_class_method :router
|
|
102
|
+
|
|
103
|
+
# Initializes a new Racket::Application object with options specified by +options+.
|
|
104
|
+
#
|
|
105
|
+
# @param [Hash] options
|
|
106
|
+
# @return [Class]
|
|
107
|
+
def self.using(options)
|
|
108
|
+
fail 'Application has already been initialized!' if @current
|
|
109
|
+
@current = self.new(options)
|
|
110
|
+
@current.reload
|
|
111
|
+
self
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Returns the view cache of the currently running application.
|
|
115
|
+
#
|
|
116
|
+
# @return [ViewCache]
|
|
117
|
+
def self.view_cache
|
|
118
|
+
@current.view_cache
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Internal dispatch handler. Should not be called directly.
|
|
122
|
+
#
|
|
123
|
+
# @param [Hash] env Rack environment
|
|
124
|
+
# @return [Array] A Rack response array
|
|
125
|
+
def call(env)
|
|
126
|
+
app.call(env)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Writes a message to the logger if there is one present.
|
|
130
|
+
#
|
|
131
|
+
# @param [String] message
|
|
132
|
+
# @param [Symbol] level
|
|
133
|
+
# @return nil
|
|
134
|
+
def inform(message, level)
|
|
135
|
+
options[:logger].send(level, message) if options[:logger]
|
|
136
|
+
nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Reloads the application, making any changes to the controller configuration visible
|
|
140
|
+
# to the application.
|
|
141
|
+
#
|
|
142
|
+
# @return [nil]
|
|
143
|
+
def reload
|
|
144
|
+
setup_routes
|
|
145
|
+
# @todo: Clear cached views/layouts
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Requires a file using the current application directory as a base path.
|
|
150
|
+
#
|
|
151
|
+
# @param [Object] args
|
|
152
|
+
# @return nil
|
|
153
|
+
def require(*args)
|
|
154
|
+
::Kernel.require Utils.build_path(*args)
|
|
155
|
+
nil
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Returns the ViewCache object associated with the current application.
|
|
159
|
+
#
|
|
160
|
+
# @return [ViewCache]
|
|
161
|
+
def view_cache
|
|
162
|
+
@view_cache ||= ViewCache.new(options[:layout_dir], options[:view_dir])
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
private
|
|
166
|
+
|
|
167
|
+
def app
|
|
168
|
+
@app ||= build_app
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def build_app
|
|
172
|
+
instance = self
|
|
173
|
+
Rack::Builder.new do
|
|
174
|
+
instance.options[:middleware].each_pair do |klass, opts|
|
|
175
|
+
Application.inform_dev("Loading middleware #{klass} with options #{opts}.")
|
|
176
|
+
use klass, opts
|
|
177
|
+
end
|
|
178
|
+
run lambda { |env| instance.router.route(env) }
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Creates a new instance of Racket::Application.
|
|
183
|
+
#
|
|
184
|
+
# @param [Hash] options
|
|
185
|
+
# @return [Racket::Application]
|
|
186
|
+
def initialize(options = {})
|
|
187
|
+
@options = default_options.merge(options)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Returns a list of default options for Racket::Application.
|
|
191
|
+
#
|
|
192
|
+
# @return [Hash]
|
|
193
|
+
def default_options
|
|
194
|
+
root_dir = Utils.build_path(Dir.pwd)
|
|
195
|
+
{
|
|
196
|
+
controller_dir: Utils.build_path(root_dir, 'controllers'),
|
|
197
|
+
default_action: :index,
|
|
198
|
+
default_layout: '_default.*',
|
|
199
|
+
default_view: nil,
|
|
200
|
+
layout_dir: Utils.build_path(root_dir, 'layouts'),
|
|
201
|
+
logger: Logger.new($stdout),
|
|
202
|
+
middleware: {
|
|
203
|
+
Rack::Session::Cookie => {
|
|
204
|
+
key: 'racket.session',
|
|
205
|
+
old_secret: SecureRandom.hex(16),
|
|
206
|
+
secret: SecureRandom.hex(16)
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
mode: :live,
|
|
210
|
+
root_dir: root_dir,
|
|
211
|
+
view_dir: Utils.build_path(root_dir, 'views')
|
|
212
|
+
}
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Loads controllers and associates each controller with a route.
|
|
216
|
+
#
|
|
217
|
+
# @return [nil]
|
|
218
|
+
def load_controllers
|
|
219
|
+
Application.inform_dev('Loading controllers.')
|
|
220
|
+
options[:last_added_controller] = []
|
|
221
|
+
@controller = nil
|
|
222
|
+
Dir.chdir(@options[:controller_dir]) do
|
|
223
|
+
files = Pathname.glob(File.join('**', '*.rb'))
|
|
224
|
+
files.map! { |file| file.to_s }
|
|
225
|
+
# Sort by longest path so that the longer paths gets matched first
|
|
226
|
+
# HttpRouter claims to be doing this already, but this "hack" is needed in order
|
|
227
|
+
# for the router to work.
|
|
228
|
+
files.sort! do |a, b|
|
|
229
|
+
b.split('/').length <=> a.split('/').length
|
|
230
|
+
end
|
|
231
|
+
files.each do |file|
|
|
232
|
+
::Kernel.require File.expand_path(file)
|
|
233
|
+
path = "/#{File.dirname(file)}"
|
|
234
|
+
path = '' if path == '/.'
|
|
235
|
+
@router.map(path, options[:last_added_controller].pop)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
options.delete(:last_added_controller)
|
|
239
|
+
Application.inform_dev('Done loading controllers.')
|
|
240
|
+
nil
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Initializes routing.
|
|
244
|
+
#
|
|
245
|
+
# @return [nil]
|
|
246
|
+
def setup_routes
|
|
247
|
+
@router = Router.new
|
|
248
|
+
load_controllers
|
|
249
|
+
nil
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
end
|
|
253
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
Racket - The noisy Rack MVC framework
|
|
3
|
+
Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
|
|
4
|
+
|
|
5
|
+
This file is part of Racket.
|
|
6
|
+
|
|
7
|
+
Racket is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU Affero General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
Racket is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU Affero General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Affero General Public License
|
|
18
|
+
along with Racket. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
module Racket
|
|
22
|
+
|
|
23
|
+
# Base controller class. Your controllers should inherit this class.
|
|
24
|
+
class Controller
|
|
25
|
+
|
|
26
|
+
# Adds a hook to one or more actions.
|
|
27
|
+
#
|
|
28
|
+
# @param [Symbol] type
|
|
29
|
+
# @param [Array] methods
|
|
30
|
+
# @param [Proc] blk
|
|
31
|
+
# @return [nil]
|
|
32
|
+
def self.add_hook(type, methods, blk)
|
|
33
|
+
key = "#{type}_hooks".to_sym
|
|
34
|
+
meths = public_instance_methods(false)
|
|
35
|
+
meths = meths & methods.map { |method| method.to_sym} unless methods.empty?
|
|
36
|
+
hooks = get_option(key) || {}
|
|
37
|
+
meths.each { |meth| hooks[meth] = blk }
|
|
38
|
+
set_option(key, hooks)
|
|
39
|
+
nil
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private_class_method :add_hook
|
|
43
|
+
|
|
44
|
+
# Adds a before hook to one or more actions. Actions should be given as a list of symbols.
|
|
45
|
+
# If no symbols are provided, *all* actions on the controller is affected.
|
|
46
|
+
#
|
|
47
|
+
# @param [Array] methods
|
|
48
|
+
# @return [nil]
|
|
49
|
+
def self.after(*methods, &blk)
|
|
50
|
+
add_hook(:after, methods, blk) if block_given?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Adds an after hook to one or more actions. Actions should be given as a list of symbols.
|
|
54
|
+
# If no symbols are provided, *all* actions on the controller is affected.
|
|
55
|
+
#
|
|
56
|
+
# @param [Array] methods
|
|
57
|
+
# @return [nil]
|
|
58
|
+
def self.before(*methods, &blk)
|
|
59
|
+
add_hook(:before, methods, blk) if block_given?
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# :nodoc:
|
|
63
|
+
def self.inherited(klass)
|
|
64
|
+
Application.options[:last_added_controller].push(klass)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns an option for the current controller class or any of the controller classes
|
|
68
|
+
# it is inheriting from.
|
|
69
|
+
#
|
|
70
|
+
# @param [Symbol] key The option to retrieve
|
|
71
|
+
# @return [Object]
|
|
72
|
+
def self.get_option(key)
|
|
73
|
+
@options ||= {}
|
|
74
|
+
return @options[key] if @options.key?(key)
|
|
75
|
+
# We are running out of controller options, do one final lookup in Application.options
|
|
76
|
+
return Application.options.fetch(key, nil) if superclass == Controller
|
|
77
|
+
superclass.get_option(key)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Sets an option for the current controller class.
|
|
81
|
+
#
|
|
82
|
+
# @param [Symbol] key
|
|
83
|
+
# @param [Object] value
|
|
84
|
+
def self.set_option(key, value)
|
|
85
|
+
@options ||= {}
|
|
86
|
+
@options[key] = value
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Returns an option from the current controller class.
|
|
90
|
+
#
|
|
91
|
+
# @param [Symbol] key
|
|
92
|
+
# @return
|
|
93
|
+
def controller_option(key)
|
|
94
|
+
self.class.get_option(key)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns a route to an action within the current controller.
|
|
98
|
+
#
|
|
99
|
+
# @param [Symbol] action
|
|
100
|
+
# @param [Array] params
|
|
101
|
+
# @return [String]
|
|
102
|
+
def rs(action, *params)
|
|
103
|
+
Application.get_route(self.class, action, params)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Returns a route to an action within another controller.
|
|
107
|
+
#
|
|
108
|
+
# @param [Class] controller
|
|
109
|
+
# @param [Symbol] action
|
|
110
|
+
# @param [Array] params
|
|
111
|
+
# @return [String]
|
|
112
|
+
def r(controller, action, *params)
|
|
113
|
+
Application.get_route(controller, action, params)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Redirects the client.
|
|
117
|
+
#
|
|
118
|
+
# @param [String] target
|
|
119
|
+
# @param [Fixnum] status
|
|
120
|
+
# @return [Object]
|
|
121
|
+
def redirect(target, status = 302)
|
|
122
|
+
racket.redirected = true
|
|
123
|
+
response.redirect(target, status)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Renders an action.
|
|
127
|
+
#
|
|
128
|
+
# @param [Symbol] action
|
|
129
|
+
# @return [String]
|
|
130
|
+
def render(action)
|
|
131
|
+
__execute(action)
|
|
132
|
+
Application.view_cache.render(self)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def __execute(action)
|
|
138
|
+
before_hooks = controller_option(:before_hooks) || {}
|
|
139
|
+
self.instance_eval &before_hooks[action] if before_hooks.key?(action)
|
|
140
|
+
meth = method(action)
|
|
141
|
+
params = racket.params[0...meth.parameters.length]
|
|
142
|
+
racket.action_result = meth.call(*params)
|
|
143
|
+
after_hooks = controller_option(:after_hooks) || {}
|
|
144
|
+
self.instance_eval &after_hooks[action] if after_hooks.key?(action)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
end
|