racket-mvc 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -49
- data/Rakefile +8 -7
- data/lib/racket/controller.rb +7 -14
- data/lib/racket/current.rb +16 -8
- data/lib/racket/helpers/file.rb +20 -12
- data/lib/racket/router.rb +24 -21
- data/lib/racket/utils.rb +44 -1
- data/lib/racket/version.rb +1 -1
- data/lib/racket/view_manager.rb +22 -25
- data/rake/utils.rb +36 -0
- data/spec/_custom.rb +3 -3
- data/spec/_default.rb +38 -45
- data/spec/_invalid.rb +1 -2
- data/spec/_request.rb +0 -2
- data/spec/racket.rb +7 -6
- data/spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb +1 -2
- data/spec/test_custom_app/controllers/sub2/custom_sub_controller_2.rb +1 -2
- data/spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb +1 -2
- data/spec/test_custom_app/controllers/sub3/inherited/custom_inherited_controller.rb +1 -2
- data/spec/test_custom_app/controllers/sub4/custom_sub_controller_4.rb +25 -0
- data/spec/test_default_app/controllers/default_root_controller.rb +1 -2
- data/spec/test_default_app/controllers/sub1/default_sub_controller_1.rb +1 -2
- data/spec/test_default_app/controllers/sub2/default_sub_controller_2.rb +3 -4
- data/spec/test_default_app/controllers/sub3/default_sub_controller_3.rb +12 -1
- data/spec/test_default_app/controllers/sub3/inherited/default_inherited_controller.rb +1 -2
- metadata +4 -3
- data/spec/test_custom_app/controllers/sub4/default_sub_controller_4.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 105b08877782c44a513558312f3e9b6af7daef75
|
4
|
+
data.tar.gz: 4ccd48feacc8788667f1ea5ab580a3cdb17cbdb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7275ee4175f164a783c9f827ddaee45f68b949ac4977c3637f6ff80e6f7662d03f0985926872d8fa68b68d4f1fa91a34c8aca3d2e3c8383cdbbdb9f3f4d45bac
|
7
|
+
data.tar.gz: 6795e2bfcca8c5671df6e65012fc60ec6ab374458d074c69f91451f9d5fde72de257530c9c32cf0e9336b16f18bc20417a2f6339edeefd09dbba91f62c5a3ab8
|
data/README.md
CHANGED
@@ -1,49 +1,49 @@
|
|
1
|
-
# Racket - The noisy Rack MVC framework
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/lasso/racket.svg?branch=master)](https://travis-ci.org/lasso/racket) [![codecov.io](https://codecov.io/github/lasso/racket/coverage.svg?branch=master)](https://codecov.io/github/lasso/racket?branch=master) [![Gem Version](https://badge.fury.io/rb/racket-mvc.svg)](http://badge.fury.io/rb/racket-mvc)
|
4
|
-
|
5
|
-
## Say what?
|
6
|
-
Yes. It is yet another framework built on rack. Using MVC. Doing silly stuff while you look the other way.
|
7
|
-
|
8
|
-
## Why? I though there were a gazillion frameworks that did the same thing already...
|
9
|
-
You are correct. There are _lots_ of Rack frameworks out there. This one does not pretend to do anything special
|
10
|
-
that you could not get from any of them.
|
11
|
-
|
12
|
-
## So, I have to ask again. Why did you create this monstrosity?
|
13
|
-
Well, when my web host suddenly started insisting on using Phusion Passenger on all of their servers
|
14
|
-
I needed to replace my old [Ramaze](http://ramaze.net/) setup without to much hassle. I tried several
|
15
|
-
other Rack framework, but none of them seemed capable of replacing my apps without some major rewrites.
|
16
|
-
|
17
|
-
## So you just though writing a whole new framework would be easier than using Rails?
|
18
|
-
Yes. Writing Rack frameworks is easy! And since I am able to decide exactly what features I want I don't
|
19
|
-
need to adopt to a large ecosystem of concepts I do not like.
|
20
|
-
|
21
|
-
## So, is it any good?
|
22
|
-
Let us just say it is good _enough_ for my needs at the moment. I plan to add more features/make stuff faster
|
23
|
-
whenever I am finished porting most of my old apps from Ramaze.
|
24
|
-
|
25
|
-
## Where are the tests?
|
26
|
-
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 on the following platforms (using [Travis CI](https://travis-ci.org/)):
|
27
|
-
|
28
|
-
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
-
|
32
|
-
- jruby
|
33
|
-
- jruby
|
34
|
-
- rbx-2
|
35
|
-
|
36
|
-
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 `rake test`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.
|
37
|
-
|
38
|
-
If you are not interested in running the tests yourself you could 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.
|
39
|
-
|
40
|
-
## Alright, I want to try using this stuff. Where are the docs?
|
41
|
-
At the moment there is not much documentation available, but I have started working on the [wiki](https://github.com/lasso/racket/wiki).
|
42
|
-
|
43
|
-
The code itself is documented using [Yard](http://yardoc.org/). The docs are not generated automatically, you need to run `rake doc` in the root directory to generate them. After running the rake task the documentation will be available in the `doc` directory.
|
44
|
-
|
45
|
-
## Why is the code licenced under the GNU Affero General Public License? I want a more liberal licence!
|
46
|
-
Because I think it is a Good Thing™ to share code. The
|
47
|
-
[GNU Affero General Public License licence](https://www.gnu.org/licenses/agpl.html) is very liberal unless you plan
|
48
|
-
on beeing egotistical. I you feel you cannot work with that, please choose
|
49
|
-
[something else](https://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#Ruby).
|
1
|
+
# Racket - The noisy Rack MVC framework
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/lasso/racket.svg?branch=master)](https://travis-ci.org/lasso/racket) [![Code Climate](https://codeclimate.com/github/lasso/racket/badges/gpa.svg)](https://codeclimate.com/github/lasso/racket) [![codecov.io](https://codecov.io/github/lasso/racket/coverage.svg?branch=master)](https://codecov.io/github/lasso/racket?branch=master) [![Gem Version](https://badge.fury.io/rb/racket-mvc.svg)](http://badge.fury.io/rb/racket-mvc)
|
4
|
+
|
5
|
+
## Say what?
|
6
|
+
Yes. It is yet another framework built on rack. Using MVC. Doing silly stuff while you look the other way.
|
7
|
+
|
8
|
+
## Why? I though there were a gazillion frameworks that did the same thing already...
|
9
|
+
You are correct. There are _lots_ of Rack frameworks out there. This one does not pretend to do anything special
|
10
|
+
that you could not get from any of them.
|
11
|
+
|
12
|
+
## So, I have to ask again. Why did you create this monstrosity?
|
13
|
+
Well, when my web host suddenly started insisting on using Phusion Passenger on all of their servers
|
14
|
+
I needed to replace my old [Ramaze](http://ramaze.net/) setup without to much hassle. I tried several
|
15
|
+
other Rack framework, but none of them seemed capable of replacing my apps without some major rewrites.
|
16
|
+
|
17
|
+
## So you just though writing a whole new framework would be easier than using Rails?
|
18
|
+
Yes. Writing Rack frameworks is easy! And since I am able to decide exactly what features I want I don't
|
19
|
+
need to adopt to a large ecosystem of concepts I do not like.
|
20
|
+
|
21
|
+
## So, is it any good?
|
22
|
+
Let us just say it is good _enough_ for my needs at the moment. I plan to add more features/make stuff faster
|
23
|
+
whenever I am finished porting most of my old apps from Ramaze.
|
24
|
+
|
25
|
+
## Where are the tests?
|
26
|
+
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 on the following platforms (using [Travis CI](https://travis-ci.org/)):
|
27
|
+
|
28
|
+
- 1.9.3
|
29
|
+
- 2.0.0
|
30
|
+
- 2.1.7
|
31
|
+
- 2.2.3
|
32
|
+
- jruby-19mode
|
33
|
+
- jruby-head
|
34
|
+
- rbx-2
|
35
|
+
|
36
|
+
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 `rake test`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.
|
37
|
+
|
38
|
+
If you are not interested in running the tests yourself you could 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.
|
39
|
+
|
40
|
+
## Alright, I want to try using this stuff. Where are the docs?
|
41
|
+
At the moment there is not much documentation available, but I have started working on the [wiki](https://github.com/lasso/racket/wiki).
|
42
|
+
|
43
|
+
The code itself is documented using [Yard](http://yardoc.org/). The docs are not generated automatically, you need to run `rake doc` in the root directory to generate them. After running the rake task the documentation will be available in the `doc` directory.
|
44
|
+
|
45
|
+
## Why is the code licenced under the GNU Affero General Public License? I want a more liberal licence!
|
46
|
+
Because I think it is a Good Thing™ to share code. The
|
47
|
+
[GNU Affero General Public License licence](https://www.gnu.org/licenses/agpl.html) is very liberal unless you plan
|
48
|
+
on beeing egotistical. I you feel you cannot work with that, please choose
|
49
|
+
[something else](https://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#Ruby).
|
data/Rakefile
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'bundler/setup'
|
3
|
+
require './rake/utils.rb'
|
3
4
|
|
4
|
-
desc
|
5
|
+
desc 'Run bacon tests'
|
5
6
|
task default: [:test]
|
6
7
|
|
7
|
-
desc
|
8
|
+
desc 'Build racket-mvc gem'
|
8
9
|
task :build_gem do
|
9
10
|
exec 'gem build racket.gemspec'
|
10
11
|
end
|
11
12
|
|
12
|
-
desc
|
13
|
+
desc 'Build yard docs'
|
13
14
|
task :doc do
|
14
15
|
exec 'yard'
|
15
16
|
end
|
16
17
|
|
17
|
-
desc
|
18
|
+
desc 'Show list of undocumented modules/classes/methods'
|
18
19
|
task :nodoc do
|
19
20
|
exec 'yard stats --list-undoc'
|
20
21
|
end
|
21
22
|
|
22
|
-
desc
|
23
|
+
desc 'Publish racket-mvc gem'
|
23
24
|
task publish_gem: [:build_gem] do
|
24
|
-
exec
|
25
|
+
exec "gem push racket-mvc#{racket_version}.gem"
|
25
26
|
end
|
26
27
|
|
27
|
-
desc
|
28
|
+
desc 'Run bacon tests'
|
28
29
|
task :test do
|
29
30
|
exec 'bacon spec/racket.rb'
|
30
31
|
end
|
data/lib/racket/controller.rb
CHANGED
@@ -24,24 +24,17 @@ module Racket
|
|
24
24
|
helper_modules = {}
|
25
25
|
helpers.each do |helper|
|
26
26
|
helper_module = helper.to_s.split('_').collect(&:capitalize).join.to_sym
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
begin
|
33
|
-
require Utils.build_path(helper_dir, helper)
|
34
|
-
rescue LoadError
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
27
|
+
Utils.run_block(NameError) do
|
28
|
+
Utils.run_block(LoadError) { require "racket/helpers/#{helper}" } ||
|
29
|
+
(helper_dir &&
|
30
|
+
Utils.run_block(LoadError) { require Utils.build_path(helper_dir, helper) }
|
31
|
+
)
|
38
32
|
helper_modules[helper] = Racket::Helpers.const_get(helper_module)
|
39
33
|
Application.inform_dev("Added helper module #{helper.inspect} to class #{self}.")
|
40
|
-
|
34
|
+
end ||
|
41
35
|
Application.inform_dev(
|
42
36
|
"Failed to add helper module #{helper.inspect} to class #{self}.", :warn
|
43
37
|
)
|
44
|
-
end
|
45
38
|
end
|
46
39
|
helper_modules
|
47
40
|
end
|
@@ -102,7 +95,7 @@ module Racket
|
|
102
95
|
helper_modules.merge!(__load_helpers(existing_helpers))
|
103
96
|
end
|
104
97
|
# Load new helpers
|
105
|
-
helpers.map!
|
98
|
+
helpers.map!(&:to_sym)
|
106
99
|
helpers.reject! { |helper| helper_modules.key?(helper) }
|
107
100
|
helper_modules.merge!(__load_helpers(helpers))
|
108
101
|
set_option(:helpers, helper_modules)
|
data/lib/racket/current.rb
CHANGED
@@ -35,17 +35,25 @@ module Racket
|
|
35
35
|
# @return [Module] A module encapsulating all state relating to the current request
|
36
36
|
def self.init(env, klass, action, params)
|
37
37
|
klass.helper if klass.get_option(:helpers).nil? # Makes sure default helpers are loaded.
|
38
|
-
|
39
|
-
request = Request.new(env)
|
40
|
-
response = Response.new
|
41
|
-
session = Session.new(env['rack.session']) if env.key?('rack.session')
|
38
|
+
properties = init_properties(action, params, env)
|
42
39
|
Module.new do
|
43
40
|
klass.get_option(:helpers).each_value { |helper| include helper }
|
44
|
-
define_method(
|
45
|
-
define_method(:request) { request }
|
46
|
-
define_method(:response) { response }
|
47
|
-
define_method(:session) { session } if env.key?('rack.session')
|
41
|
+
properties.each_pair { |key, value| define_method(key) { value } }
|
48
42
|
end
|
49
43
|
end
|
44
|
+
|
45
|
+
def self.init_properties(action, params, env)
|
46
|
+
properties =
|
47
|
+
{
|
48
|
+
racket: State.new(action, nil, params),
|
49
|
+
request: Request.new(env),
|
50
|
+
response: Response.new
|
51
|
+
}
|
52
|
+
session = env.fetch('rack.session', nil)
|
53
|
+
properties[:session] = Session.new(session) if session
|
54
|
+
properties
|
55
|
+
end
|
56
|
+
|
57
|
+
private_class_method :init_properties
|
50
58
|
end
|
51
59
|
end
|
data/lib/racket/helpers/file.rb
CHANGED
@@ -28,12 +28,7 @@ module Racket
|
|
28
28
|
# @return [Array]
|
29
29
|
def send_file(file, options = {})
|
30
30
|
file = Utils.build_path(file)
|
31
|
-
|
32
|
-
respond!(
|
33
|
-
404,
|
34
|
-
{ 'Content-Type' => 'text/plain' },
|
35
|
-
Rack::Utils::HTTP_STATUS_CODES[404]
|
36
|
-
) unless Utils.file_readable? (file)
|
31
|
+
_send_file_check_file_readable(file)
|
37
32
|
headers = {}
|
38
33
|
mime_type = options.fetch(:mime_type, nil)
|
39
34
|
# Calculate MIME type if it was not already specified.
|
@@ -41,15 +36,28 @@ module Racket
|
|
41
36
|
headers['Content-Type'] = mime_type
|
42
37
|
# Set Content-Disposition (and a file name) if the file should be downloaded
|
43
38
|
# instead of displayed inline.
|
44
|
-
|
45
|
-
filename = options.fetch(:filename, nil).to_s
|
46
|
-
headers['Content-Disposition'] = 'attachment'
|
47
|
-
headers['Content-Disposition'] << sprintf('; filename="%s"', filename) unless
|
48
|
-
filename.empty?
|
49
|
-
end
|
39
|
+
_send_file_set_content_disposition(options, headers)
|
50
40
|
# Send response
|
51
41
|
respond!(200, headers, ::File.read(file))
|
52
42
|
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def _send_file_check_file_readable(file)
|
47
|
+
# Respond with a 404 Not Found if the file cannot be read.
|
48
|
+
respond!(
|
49
|
+
404,
|
50
|
+
{ 'Content-Type' => 'text/plain' },
|
51
|
+
Rack::Utils::HTTP_STATUS_CODES[404]
|
52
|
+
) unless Utils.file_readable?(file)
|
53
|
+
end
|
54
|
+
|
55
|
+
def _send_file_set_content_disposition(options, headers)
|
56
|
+
return unless options.fetch(:download, false)
|
57
|
+
filename = options.fetch(:filename, nil).to_s
|
58
|
+
headers['Content-Disposition'] = 'attachment'
|
59
|
+
headers['Content-Disposition'] << format('; filename="%s"', filename) unless filename.empty?
|
60
|
+
end
|
53
61
|
end
|
54
62
|
end
|
55
63
|
end
|
data/lib/racket/router.rb
CHANGED
@@ -23,38 +23,41 @@ require 'http_router'
|
|
23
23
|
module Racket
|
24
24
|
# Handles routing in Racket applications.
|
25
25
|
class Router
|
26
|
+
attr_reader :action_cache
|
27
|
+
attr_reader :routes
|
28
|
+
|
26
29
|
def initialize
|
27
30
|
@router = HttpRouter.new
|
28
|
-
@
|
29
|
-
@
|
31
|
+
@routes = {}
|
32
|
+
@action_cache = {}
|
30
33
|
end
|
31
34
|
|
32
35
|
# Caches available actions for each controller class. This also works for controller classes
|
33
36
|
# that inherit from other controller classes.
|
34
37
|
#
|
35
|
-
# @param [Class]
|
38
|
+
# @param [Class] controller_class
|
36
39
|
# @return [nil]
|
37
|
-
def cache_actions(
|
40
|
+
def cache_actions(controller_class)
|
38
41
|
actions = SortedSet.new
|
39
|
-
|
40
|
-
while
|
41
|
-
actions.merge(
|
42
|
-
|
42
|
+
current_class = controller_class
|
43
|
+
while current_class < Controller
|
44
|
+
actions.merge(current_class.public_instance_methods(false))
|
45
|
+
current_class = current_class.superclass
|
43
46
|
end
|
44
|
-
(@
|
47
|
+
(@action_cache[controller_class] = actions.to_a) && nil
|
45
48
|
end
|
46
49
|
|
47
50
|
# Returns a route to the specified controller/action/parameter combination.
|
48
51
|
#
|
49
|
-
# @param [Class]
|
52
|
+
# @param [Class] controller_class
|
50
53
|
# @param [Symbol] action
|
51
54
|
# @param [Array] params
|
52
55
|
# @return [String]
|
53
|
-
def get_route(
|
54
|
-
fail "Cannot find controller #{
|
56
|
+
def get_route(controller_class, action, params)
|
57
|
+
fail "Cannot find controller #{controller_class}" unless @routes.key?(controller_class)
|
55
58
|
params.flatten!
|
56
59
|
route = ''
|
57
|
-
route << @
|
60
|
+
route << @routes[controller_class]
|
58
61
|
route << "/#{action}" unless action.nil?
|
59
62
|
route << "/#{params.join('/')}" unless params.empty?
|
60
63
|
route = route[1..-1] if route.start_with?('//') # Special case for root path
|
@@ -64,14 +67,14 @@ module Racket
|
|
64
67
|
# Maps a controller to the specified path.
|
65
68
|
#
|
66
69
|
# @param [String] path
|
67
|
-
# @param [Class]
|
70
|
+
# @param [Class] controller_class
|
68
71
|
# @return [nil]
|
69
|
-
def map(path,
|
70
|
-
|
71
|
-
Application.inform_dev("Mapping #{
|
72
|
-
@router.add("#{path}(/*params)").to(
|
73
|
-
@
|
74
|
-
cache_actions(
|
72
|
+
def map(path, controller_class)
|
73
|
+
controller_class_base_path = path.empty? ? '/' : path
|
74
|
+
Application.inform_dev("Mapping #{controller_class} to #{controller_class_base_path}.")
|
75
|
+
@router.add("#{path}(/*params)").to(controller_class)
|
76
|
+
@routes[controller_class] = controller_class_base_path
|
77
|
+
cache_actions(controller_class) && nil
|
75
78
|
end
|
76
79
|
|
77
80
|
# @todo: Allow the user to set custom handlers for different errors
|
@@ -105,7 +108,7 @@ module Racket
|
|
105
108
|
action = params.empty? ? target_klass.get_option(:default_action) : params.shift.to_sym
|
106
109
|
|
107
110
|
# Check if action is available on target
|
108
|
-
return render_error(404) unless @
|
111
|
+
return render_error(404) unless @action_cache[target_klass].include?(action)
|
109
112
|
|
110
113
|
# Rewrite PATH_INFO to reflect that we split out the parameters
|
111
114
|
env['PATH_INFO'] = env['PATH_INFO']
|
data/lib/racket/utils.rb
CHANGED
@@ -19,6 +19,38 @@
|
|
19
19
|
module Racket
|
20
20
|
# Collects utilities needed by different objects in Racket.
|
21
21
|
class Utils
|
22
|
+
# Handles exceptions dynamically
|
23
|
+
class ExceptionHandler
|
24
|
+
# Runs a block.
|
25
|
+
# If no exceptions are raised, this method returns true.
|
26
|
+
# If any of the provided error types are raised, this method returns false.
|
27
|
+
# If any other exception is raised, this method will just forward the exception.
|
28
|
+
#
|
29
|
+
# @param [Array] errors
|
30
|
+
# @return [true|flase]
|
31
|
+
def self.run_block(errors)
|
32
|
+
fail 'Need a block' unless block_given?
|
33
|
+
begin
|
34
|
+
true.tap { yield }
|
35
|
+
rescue boolean_module(errors)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns an anonymous module that can be used to rescue exceptions dynamically.
|
41
|
+
def self.boolean_module(errors)
|
42
|
+
Module.new do
|
43
|
+
(class << self; self; end).instance_eval do
|
44
|
+
define_method(:===) do |error|
|
45
|
+
errors.any? { |e| error.class <= e }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private_class_method :boolean_module
|
52
|
+
end
|
53
|
+
|
22
54
|
# Builds and returns a path in the file system from the provided arguments. The first element
|
23
55
|
# in the argument list can be either absolute or relative, all other arguments must be relative,
|
24
56
|
# otherwise they will be removed from the final path.
|
@@ -29,7 +61,7 @@ module Racket
|
|
29
61
|
if args.empty?
|
30
62
|
path = Pathname.pwd
|
31
63
|
else
|
32
|
-
args.map!
|
64
|
+
args.map!(&:to_s)
|
33
65
|
path = Pathname.new(args.shift)
|
34
66
|
path = Pathname.new(Application.options[:root_dir]).join(path) if path.relative?
|
35
67
|
args.each do |arg|
|
@@ -50,5 +82,16 @@ module Racket
|
|
50
82
|
pathname = Pathname.new(path)
|
51
83
|
pathname.exist? && pathname.file? && pathname.readable?
|
52
84
|
end
|
85
|
+
|
86
|
+
# Runs a block.
|
87
|
+
# If no exceptions are raised, this method returns true.
|
88
|
+
# If any of the provided error types are raised, this method returns false.
|
89
|
+
# If any other exception is raised, this method will just forward the exception.
|
90
|
+
#
|
91
|
+
# @param [Array] errors
|
92
|
+
# @return [true|flase]
|
93
|
+
def self.run_block(*errors, &block)
|
94
|
+
ExceptionHandler.run_block(errors, &block)
|
95
|
+
end
|
53
96
|
end
|
54
97
|
end
|
data/lib/racket/version.rb
CHANGED
data/lib/racket/view_manager.rb
CHANGED
@@ -21,7 +21,6 @@ require 'tilt'
|
|
21
21
|
module Racket
|
22
22
|
# Handles rendering in Racket applications.
|
23
23
|
class ViewManager
|
24
|
-
|
25
24
|
attr_reader :layout_cache
|
26
25
|
attr_reader :view_cache
|
27
26
|
|
@@ -77,6 +76,26 @@ module Racket
|
|
77
76
|
proc.call(*proc_args).to_s
|
78
77
|
end
|
79
78
|
|
79
|
+
# Returns a cached template. If the template has not been cached yet, this method will run a
|
80
|
+
# lookup against the provided parameters.
|
81
|
+
#
|
82
|
+
# @param [String] path
|
83
|
+
# @param [Racket::Controller] controller
|
84
|
+
# @param [Symbol] type
|
85
|
+
def ensure_in_cache(path, controller, type)
|
86
|
+
store = instance_variable_get("@#{type}_cache".to_sym)
|
87
|
+
return store[path] if store.key?(path)
|
88
|
+
base_dir = instance_variable_get("@#{type}_base_dir".to_sym)
|
89
|
+
default_template = controller.controller_option("default_#{type}".to_sym)
|
90
|
+
template = lookup_template(base_dir, path)
|
91
|
+
template =
|
92
|
+
lookup_default_template(base_dir, File.dirname(path), default_template) unless template
|
93
|
+
Application.inform_dev(
|
94
|
+
"Using #{type} #{template.inspect} for #{controller.class}.#{controller.racket.action}."
|
95
|
+
)
|
96
|
+
store[path] = template
|
97
|
+
end
|
98
|
+
|
80
99
|
# Tries to locate a layout matching +path+ in the file system and returns the path if a
|
81
100
|
# matching file is found. If no matching file is found, +nil+ is returned. The result is cached,
|
82
101
|
# meaning that the filesystem lookup for a specific path will only happen once.
|
@@ -85,18 +104,7 @@ module Racket
|
|
85
104
|
# @param [Racket::Controller] controller
|
86
105
|
# @return [String|nil]
|
87
106
|
def get_layout(path, controller)
|
88
|
-
|
89
|
-
layout = lookup_template(@layout_base_dir, path)
|
90
|
-
layout =
|
91
|
-
lookup_default_template(
|
92
|
-
@layout_base_dir, File.dirname(path), controller.controller_option(:default_layout)
|
93
|
-
) unless layout
|
94
|
-
Application.inform_dev(
|
95
|
-
"Using layout #{layout.inspect} for #{controller.class}.#{controller.racket.action}."
|
96
|
-
)
|
97
|
-
@layout_cache[path] = layout
|
98
|
-
end
|
99
|
-
layout = @layout_cache[path]
|
107
|
+
layout = ensure_in_cache(path, controller, :layout)
|
100
108
|
if layout.is_a?(Proc)
|
101
109
|
layout =
|
102
110
|
lookup_template(
|
@@ -115,18 +123,7 @@ module Racket
|
|
115
123
|
# @param [Racket::Controller] controller
|
116
124
|
# @return [String|nil]
|
117
125
|
def get_view(path, controller)
|
118
|
-
|
119
|
-
view = lookup_template(@view_base_dir, path)
|
120
|
-
view =
|
121
|
-
lookup_default_template(
|
122
|
-
@view_base_dir, File.dirname(path), controller.controller_option(:default_view)
|
123
|
-
) unless view
|
124
|
-
Application.inform_dev(
|
125
|
-
"Using view #{view.inspect} for #{controller.class}.#{controller.racket.action}."
|
126
|
-
)
|
127
|
-
@view_cache[path] = view
|
128
|
-
end
|
129
|
-
view = @view_cache[path]
|
126
|
+
view = ensure_in_cache(path, controller, :view)
|
130
127
|
if view.is_a?(Proc)
|
131
128
|
view =
|
132
129
|
lookup_template(
|
data/rake/utils.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Racket - The noisy Rack MVC framework
|
2
|
+
# Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
|
3
|
+
#
|
4
|
+
# This file is part of Racket.
|
5
|
+
#
|
6
|
+
# Racket is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Racket is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Affero General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
17
|
+
# along with Racket. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
def racket_version
|
20
|
+
mod = Module.new
|
21
|
+
mod.module_eval(
|
22
|
+
File.read(
|
23
|
+
File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'racket', 'version.rb')
|
24
|
+
)
|
25
|
+
)
|
26
|
+
mod::Racket::Version.current
|
27
|
+
end
|
28
|
+
|
29
|
+
def racket_files
|
30
|
+
Dir.chdir(File.dirname(File.dirname(__FILE__))) do
|
31
|
+
files = FileList['lib/**/*.rb'].to_a
|
32
|
+
files.concat(FileList['rake/**/*'].to_a)
|
33
|
+
files.concat(FileList['spec/**/*'].to_a)
|
34
|
+
files.concat(FileList['COPYING.AGPL', 'Rakefile', 'README.md'].to_a)
|
35
|
+
end
|
36
|
+
end
|
data/spec/_custom.rb
CHANGED
@@ -50,14 +50,14 @@ describe 'A custom Racket test Application' do
|
|
50
50
|
last_response.headers.key?('X-Hook-Action').should.equal(true)
|
51
51
|
last_response.headers['X-Hook-Action'].should.equal('run')
|
52
52
|
response = JSON.parse(last_response.body)
|
53
|
-
response.should.equal([
|
53
|
+
response.should.equal(['Data added in before block', 'Data added in action'])
|
54
54
|
end
|
55
55
|
|
56
56
|
it 'should let Rack::ShowExceptions handle the error' do
|
57
57
|
get '/sub1/epic_fail'
|
58
58
|
last_response.status.should.equal(500)
|
59
59
|
last_response.headers['Content-Type'].should.equal('text/plain')
|
60
|
-
last_response.body.should.match(
|
60
|
+
last_response.body.should.match(/^RuntimeError: Epic fail!/)
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should be able to render custom files' do
|
@@ -104,7 +104,7 @@ describe 'A custom Racket test Application' do
|
|
104
104
|
last_response.status.should.equal(404)
|
105
105
|
last_response.headers['Content-Type'].should.equal('text/plain')
|
106
106
|
last_response.headers.key?('Content-Disposition').should.equal(false)
|
107
|
-
last_response.body.should.equal(
|
107
|
+
last_response.body.should.equal('Not Found')
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'should be able to handle dynamic layouts and views' do
|
data/spec/_default.rb
CHANGED
@@ -10,33 +10,27 @@ describe 'A default Racket test Application' do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'has mapped controllers correctly' do
|
13
|
-
|
14
|
-
app.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
actions_by_controller[DefaultSubController2].length.should.equal(5)
|
35
|
-
actions_by_controller[DefaultSubController2].include?(:index).should.equal(true)
|
36
|
-
actions_by_controller[DefaultSubController2].include?(:current_action).should.equal(true)
|
37
|
-
actions_by_controller[DefaultSubController2].include?(:current_params).should.equal(true)
|
38
|
-
actions_by_controller[DefaultSubController3].should.equal([:index])
|
39
|
-
actions_by_controller[DefaultInheritedController].should.equal([:index])
|
13
|
+
app.router.routes.length.should.equal(5)
|
14
|
+
app.router.routes[DefaultRootController].should.equal('/')
|
15
|
+
app.router.routes[DefaultSubController1].should.equal('/sub1')
|
16
|
+
app.router.routes[DefaultSubController2].should.equal('/sub2')
|
17
|
+
app.router.routes[DefaultSubController3].should.equal('/sub3')
|
18
|
+
app.router.routes[DefaultInheritedController].should.equal('/sub3/inherited')
|
19
|
+
|
20
|
+
app.router.action_cache[DefaultRootController].length.should.equal(5)
|
21
|
+
app.router.action_cache[DefaultRootController].include?(:index).should.equal(true)
|
22
|
+
app.router.action_cache[DefaultRootController].include?(:my_first_route).should.equal(true)
|
23
|
+
app.router.action_cache[DefaultRootController].include?(:my_second_route).should.equal(true)
|
24
|
+
app.router.action_cache[DefaultSubController1].length.should.equal(4)
|
25
|
+
app.router.action_cache[DefaultSubController1].include?(:route_to_root).should.equal(true)
|
26
|
+
app.router.action_cache[DefaultSubController1].include?(:route_to_nonexisting)
|
27
|
+
.should.equal(true)
|
28
|
+
app.router.action_cache[DefaultSubController2].length.should.equal(5)
|
29
|
+
app.router.action_cache[DefaultSubController2].include?(:index).should.equal(true)
|
30
|
+
app.router.action_cache[DefaultSubController2].include?(:current_action).should.equal(true)
|
31
|
+
app.router.action_cache[DefaultSubController2].include?(:current_params).should.equal(true)
|
32
|
+
app.router.action_cache[DefaultSubController3].should.equal([:index])
|
33
|
+
app.router.action_cache[DefaultInheritedController].should.equal([:index])
|
40
34
|
end
|
41
35
|
|
42
36
|
it 'should set rack variables correctly' do
|
@@ -46,7 +40,7 @@ describe 'A default Racket test Application' do
|
|
46
40
|
|
47
41
|
get '/sub2/current_params/foo/bar/baz'
|
48
42
|
last_response.status.should.equal(200)
|
49
|
-
JSON.parse(last_response.body).should.equal(
|
43
|
+
JSON.parse(last_response.body).should.equal(%w(foo bar baz))
|
50
44
|
end
|
51
45
|
|
52
46
|
it 'returns the correct respnse when calling index action' do
|
@@ -107,27 +101,27 @@ describe 'A default Racket test Application' do
|
|
107
101
|
end
|
108
102
|
|
109
103
|
it 'should be able to log messages to everybody' do
|
110
|
-
|
104
|
+
original_logger = app.options[:logger]
|
111
105
|
sio = StringIO.new
|
112
106
|
app.options[:logger] = Logger.new(sio)
|
113
|
-
app.inform_all('Informational message')
|
107
|
+
app.inform_all('Informational message')
|
114
108
|
sio.string.should.match(/Informational message/)
|
115
|
-
app.options[:logger] =
|
109
|
+
app.options[:logger] = original_logger
|
116
110
|
end
|
117
111
|
|
118
112
|
it 'should be able to log messages to developer' do
|
119
|
-
|
120
|
-
|
113
|
+
original_logger = app.options[:logger]
|
114
|
+
original_mode = app.options[:mode]
|
121
115
|
sio = StringIO.new
|
122
116
|
app.options[:logger] = Logger.new(sio)
|
123
117
|
app.options[:mode] = :live
|
124
|
-
app.inform_dev('Development message')
|
118
|
+
app.inform_dev('Development message')
|
125
119
|
sio.string.should.be.empty
|
126
120
|
app.options[:mode] = :dev
|
127
|
-
app.inform_dev('Hey, listen up!')
|
128
|
-
sio.string.should.match(
|
129
|
-
app.options[:mode] =
|
130
|
-
app.options[:logger] =
|
121
|
+
app.inform_dev('Hey, listen up!')
|
122
|
+
sio.string.should.match(/Hey, listen up!/)
|
123
|
+
app.options[:mode] = original_mode
|
124
|
+
app.options[:logger] = original_logger
|
131
125
|
end
|
132
126
|
|
133
127
|
it 'should be able to set and clear session variables' do
|
@@ -138,7 +132,7 @@ describe 'A default Racket test Application' do
|
|
138
132
|
response.keys.should.be.empty
|
139
133
|
get '/session_as_json?foo=bar'
|
140
134
|
last_response.headers.keys.should.include('Set-Cookie')
|
141
|
-
last_response.headers['Set-Cookie'].should.match(
|
135
|
+
last_response.headers['Set-Cookie'].should.match(/racket.session=/)
|
142
136
|
response = JSON.parse(last_response.body)
|
143
137
|
response.class.should.equal(Hash)
|
144
138
|
response.keys.length.should.equal(2)
|
@@ -146,7 +140,7 @@ describe 'A default Racket test Application' do
|
|
146
140
|
response.keys.should.include('session_id')
|
147
141
|
get '/session_as_json?baz=quux'
|
148
142
|
last_response.headers.keys.should.include('Set-Cookie')
|
149
|
-
last_response.headers['Set-Cookie'].should.match(
|
143
|
+
last_response.headers['Set-Cookie'].should.match(/racket.session=/)
|
150
144
|
response = JSON.parse(last_response.body)
|
151
145
|
response.class.should.equal(Hash)
|
152
146
|
response.keys.length.should.equal(3)
|
@@ -155,14 +149,14 @@ describe 'A default Racket test Application' do
|
|
155
149
|
response.keys.should.include('session_id')
|
156
150
|
get '/session_as_json?drop_session'
|
157
151
|
last_response.headers.keys.should.include('Set-Cookie')
|
158
|
-
last_response.headers['Set-Cookie'].should.match(
|
152
|
+
last_response.headers['Set-Cookie'].should.match(/racket.session=/)
|
159
153
|
response = JSON.parse(last_response.body)
|
160
154
|
response.class.should.equal(Hash)
|
161
155
|
response.keys.should.be.empty
|
162
156
|
get '/session_strings'
|
163
157
|
response = JSON.parse(last_response.body)
|
164
158
|
response.length.should.equal(3)
|
165
|
-
response.each { |elem| elem.should.match(
|
159
|
+
response.each { |elem| elem.should.match(/Racket::Session/) }
|
166
160
|
end
|
167
161
|
|
168
162
|
it 'should be able to build paths correctly' do
|
@@ -173,7 +167,7 @@ describe 'A default Racket test Application' do
|
|
173
167
|
end
|
174
168
|
|
175
169
|
it 'should handle GET parameters correctly' do
|
176
|
-
get '/sub2/
|
170
|
+
get '/sub2/some_get_data/?data1=foo&data3=bar'
|
177
171
|
last_response.status.should.equal(200)
|
178
172
|
response = JSON.parse(last_response.body, symbolize_names: true)
|
179
173
|
response.class.should.equal(Hash)
|
@@ -184,7 +178,7 @@ describe 'A default Racket test Application' do
|
|
184
178
|
end
|
185
179
|
|
186
180
|
it 'should handle POST parameters correctly' do
|
187
|
-
post '/sub2/
|
181
|
+
post '/sub2/some_post_data', data1: 'foo', data3: 'bar'
|
188
182
|
last_response.status.should.equal(200)
|
189
183
|
response = JSON.parse(last_response.body, symbolize_names: true)
|
190
184
|
response.class.should.equal(Hash)
|
@@ -207,5 +201,4 @@ describe 'A default Racket test Application' do
|
|
207
201
|
last_response.headers['Content-Type'].should.equal('text/plain')
|
208
202
|
last_response.body.should.equal('500 Internal Server Error')
|
209
203
|
end
|
210
|
-
|
211
204
|
end
|
data/spec/_invalid.rb
CHANGED
data/spec/_request.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
describe 'Racket::Request should override Rack::Request correctly' do
|
2
|
-
|
3
2
|
r = Racket::Request.new({}).freeze
|
4
3
|
|
5
4
|
describe 'Racket::Request should inherit some methods from Rack::Request' do
|
@@ -45,5 +44,4 @@ describe 'Racket::Request should override Rack::Request correctly' do
|
|
45
44
|
end
|
46
45
|
end
|
47
46
|
end
|
48
|
-
|
49
47
|
end
|
data/spec/racket.rb
CHANGED
@@ -11,8 +11,9 @@ if ENV['CI'] == 'true'
|
|
11
11
|
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
TEST_DIR = File.absolute_path(File.dirname(__FILE__))
|
15
|
+
TEST_DEFAULT_APP_DIR = File.join(TEST_DIR, 'test_default_app')
|
16
|
+
TEST_CUSTOM_APP_DIR = File.join(TEST_DIR, 'test_custom_app')
|
16
17
|
|
17
18
|
require 'racket'
|
18
19
|
|
@@ -22,9 +23,9 @@ require 'racket/helpers/file.rb'
|
|
22
23
|
require 'rack/test'
|
23
24
|
require 'bacon'
|
24
25
|
|
25
|
-
|
26
|
+
require File.join(TEST_DIR, '_request.rb')
|
26
27
|
|
27
|
-
Dir.chdir(TEST_DEFAULT_APP_DIR) {
|
28
|
-
Dir.chdir(TEST_CUSTOM_APP_DIR) {
|
28
|
+
Dir.chdir(TEST_DEFAULT_APP_DIR) { require File.join(TEST_DIR, '_default.rb') }
|
29
|
+
Dir.chdir(TEST_CUSTOM_APP_DIR) { require File.join(TEST_DIR, '_custom.rb') }
|
29
30
|
|
30
|
-
|
31
|
+
require File.join(TEST_DIR, '_invalid.rb')
|
@@ -1,5 +1,5 @@
|
|
1
|
+
# Custom sub controller 1
|
1
2
|
class CustomSubController1 < Racket::Controller
|
2
|
-
|
3
3
|
helper :file
|
4
4
|
|
5
5
|
def index
|
@@ -37,5 +37,4 @@ class CustomSubController1 < Racket::Controller
|
|
37
37
|
def send_nonexisting_file
|
38
38
|
send_file('files/no_such_thing.jpg')
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
+
# Custom sub controller 3
|
1
2
|
class CustomSubController3 < Racket::Controller
|
2
|
-
|
3
3
|
set_option(:top_secret, 42)
|
4
4
|
|
5
5
|
def index
|
@@ -23,5 +23,4 @@ class CustomSubController3 < Racket::Controller
|
|
23
23
|
obj.instance_eval { @secret = 42 }
|
24
24
|
render_template('files/secret.erb', obj)
|
25
25
|
end
|
26
|
-
|
27
26
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Custom sub controller 4
|
2
|
+
class CustomSubController4 < Racket::Controller
|
3
|
+
set_option :default_layout, -> { 'layout.erb' }
|
4
|
+
|
5
|
+
set_option :default_view,
|
6
|
+
lambda { |action|
|
7
|
+
case action
|
8
|
+
when :foo then 'myfoo.erb'
|
9
|
+
when :bar then 'mybar.erb'
|
10
|
+
else 'default.erb'
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
def foo
|
15
|
+
@data = 'FOO'
|
16
|
+
end
|
17
|
+
|
18
|
+
def bar
|
19
|
+
@data = 'BAR'
|
20
|
+
end
|
21
|
+
|
22
|
+
def baz
|
23
|
+
@data = 'BAZ'
|
24
|
+
end
|
25
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
|
+
# Default root controller
|
3
4
|
class DefaultRootController < Racket::Controller
|
4
|
-
|
5
5
|
def index
|
6
6
|
"#{self.class}::#{__method__}"
|
7
7
|
end
|
@@ -28,5 +28,4 @@ class DefaultRootController < Racket::Controller
|
|
28
28
|
def session_strings
|
29
29
|
[session.inspect, session.to_s, session.to_str].to_json
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
+
# Default sub controller 2
|
1
2
|
class DefaultSubController2 < Racket::Controller
|
2
|
-
|
3
3
|
def index
|
4
4
|
"#{self.class}::#{__method__}"
|
5
5
|
end
|
@@ -12,7 +12,7 @@ class DefaultSubController2 < Racket::Controller
|
|
12
12
|
racket.params.to_json
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
15
|
+
def some_get_data
|
16
16
|
data = {}
|
17
17
|
[:data1, :data2, :data3].each do |d|
|
18
18
|
data[d] = request.get(d)
|
@@ -20,12 +20,11 @@ class DefaultSubController2 < Racket::Controller
|
|
20
20
|
data.to_json
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
23
|
+
def some_post_data
|
24
24
|
data = {}
|
25
25
|
[:data1, :data2, :data3].each do |d|
|
26
26
|
data[d] = request.post(d)
|
27
27
|
end
|
28
28
|
data.to_json
|
29
29
|
end
|
30
|
-
|
31
30
|
end
|
@@ -1,7 +1,18 @@
|
|
1
|
+
# Default sub controller 3
|
1
2
|
class DefaultSubController3 < Racket::Controller
|
2
|
-
|
3
3
|
def index
|
4
4
|
"#{self.class}::#{__method__}"
|
5
5
|
end
|
6
6
|
|
7
|
+
protected
|
8
|
+
|
9
|
+
def protected_method
|
10
|
+
"I'm protected"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def private_method
|
16
|
+
"I'm private"
|
17
|
+
end
|
7
18
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: racket-mvc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Olsson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http_router
|
@@ -159,6 +159,7 @@ files:
|
|
159
159
|
- lib/racket/utils.rb
|
160
160
|
- lib/racket/version.rb
|
161
161
|
- lib/racket/view_manager.rb
|
162
|
+
- rake/utils.rb
|
162
163
|
- spec/_custom.rb
|
163
164
|
- spec/_default.rb
|
164
165
|
- spec/_invalid.rb
|
@@ -168,7 +169,7 @@ files:
|
|
168
169
|
- spec/test_custom_app/controllers/sub2/custom_sub_controller_2.rb
|
169
170
|
- spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb
|
170
171
|
- spec/test_custom_app/controllers/sub3/inherited/custom_inherited_controller.rb
|
171
|
-
- spec/test_custom_app/controllers/sub4/
|
172
|
+
- spec/test_custom_app/controllers/sub4/custom_sub_controller_4.rb
|
172
173
|
- spec/test_custom_app/extra/blob.rb
|
173
174
|
- spec/test_custom_app/extra/blob/inner_blob.rb
|
174
175
|
- spec/test_custom_app/files/plain_text.txt
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class CustomSubController4 < Racket::Controller
|
2
|
-
|
3
|
-
set_option :default_layout, lambda { 'layout.erb' }
|
4
|
-
|
5
|
-
set_option :default_view,
|
6
|
-
lambda { |action|
|
7
|
-
case action
|
8
|
-
when :foo then 'myfoo.erb'
|
9
|
-
when :bar then 'mybar.erb'
|
10
|
-
else 'default.erb'
|
11
|
-
end
|
12
|
-
}
|
13
|
-
|
14
|
-
def foo
|
15
|
-
@data = 'FOO'
|
16
|
-
end
|
17
|
-
|
18
|
-
def bar
|
19
|
-
@data = 'BAR'
|
20
|
-
end
|
21
|
-
|
22
|
-
def baz
|
23
|
-
@data = 'BAZ'
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|