tanuki 0.3.1 → 0.4.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/README.rdoc +5 -4
- data/app/tanuki/controller/{link.thtml → controller.link.thtml} +0 -0
- data/app/tanuki/controller/controller.page.thtml +14 -0
- data/app/tanuki/controller/controller.rb +1 -2
- data/app/tanuki/controller/controller.title.ttxt +1 -0
- data/app/tanuki/controller/controller.view.thtml +3 -0
- data/app/tanuki/fetcher/sequel/sequel.rb +34 -0
- data/app/tanuki/manager/controller/controller.rb +1 -1
- data/app/tanuki/manager/page/page.rb +1 -1
- data/app/tanuki/meta_model/{manager.ttxt → meta_model.manager.ttxt} +0 -0
- data/app/tanuki/meta_model/{manager_base.ttxt → meta_model.manager_base.ttxt} +0 -0
- data/app/tanuki/meta_model/{model.ttxt → meta_model.model.ttxt} +0 -0
- data/app/tanuki/meta_model/{model_base.ttxt → meta_model.model_base.ttxt} +0 -0
- data/app/tanuki/meta_model/meta_model.rb +1 -2
- data/app/tanuki/model/controller/controller.rb +1 -1
- data/app/tanuki/model/page/page.rb +1 -1
- data/app/tanuki/page/missing/{default.thtml → missing.page.thtml} +1 -1
- data/app/tanuki/page/missing/missing.rb +3 -2
- data/app/user/page/home/home.rb +2 -0
- data/app/user/page/home/home.title.thtml +1 -0
- data/app/user/page/home/home.view.css +88 -0
- data/app/user/page/home/home.view.thtml +22 -0
- data/bin/tanuki +2 -1
- data/config/common.rb +1 -0
- data/config/common_application.rb +3 -6
- data/config/development_application.rb +0 -3
- data/lib/tanuki.rb +8 -7
- data/lib/tanuki/application.rb +108 -81
- data/lib/tanuki/argument.rb +10 -5
- data/lib/tanuki/argument/integer_range.rb +4 -2
- data/lib/tanuki/{behavior/object_behavior.rb → base_behavior.rb} +21 -4
- data/lib/tanuki/configurator.rb +20 -8
- data/lib/tanuki/const.rb +32 -0
- data/lib/tanuki/context.rb +18 -7
- data/lib/tanuki/controller.rb +517 -0
- data/lib/tanuki/css_compressor.rb +50 -0
- data/lib/tanuki/extensions/module.rb +21 -5
- data/lib/tanuki/extensions/rack/frozen_route.rb +35 -0
- data/lib/tanuki/extensions/rack/static_dir.rb +1 -1
- data/lib/tanuki/extensions/sequel/model.rb +7 -0
- data/lib/tanuki/i18n.rb +8 -6
- data/lib/tanuki/loader.rb +166 -33
- data/lib/tanuki/meta_model.rb +176 -0
- data/lib/tanuki/{behavior/model_behavior.rb → model_behavior.rb} +7 -3
- data/lib/tanuki/model_generator.rb +49 -29
- data/lib/tanuki/template_compiler.rb +72 -41
- data/lib/tanuki/utility.rb +11 -4
- data/lib/tanuki/utility/create.rb +52 -11
- data/lib/tanuki/utility/generate.rb +16 -10
- data/lib/tanuki/utility/version.rb +1 -1
- data/lib/tanuki/version.rb +7 -2
- metadata +50 -66
- data/app/tanuki/controller/default.thtml +0 -5
- data/app/tanuki/controller/index.thtml +0 -1
- data/app/user/page/index/default.thtml +0 -121
- data/app/user/page/index/index.rb +0 -2
- data/config/test_application.rb +0 -2
- data/lib/tanuki/behavior/controller_behavior.rb +0 -366
- data/lib/tanuki/behavior/meta_model_behavior.rb +0 -160
- data/lib/tanuki/extensions/rack/builder.rb +0 -26
- data/lib/tanuki/extensions/rack/server.rb +0 -18
- data/lib/tanuki/launcher.rb +0 -21
- data/lib/tanuki/utility/server.rb +0 -23
data/README.rdoc
CHANGED
@@ -11,9 +11,10 @@ Right now it's very raw, so don't expect things to work properly.
|
|
11
11
|
Fire up the terminal and type:
|
12
12
|
|
13
13
|
$ gem install tanuki
|
14
|
-
$ tanuki
|
15
|
-
|
16
|
-
|
14
|
+
$ tanuki create test
|
15
|
+
$ cd test
|
16
|
+
$ bundle install
|
17
|
+
$ rackup -p 3000
|
17
18
|
|
18
19
|
View the result at: http://localhost:3000
|
19
20
|
|
@@ -27,4 +28,4 @@ Tanuki is thankful to:
|
|
27
28
|
|
28
29
|
* All of the core contributors
|
29
30
|
* Erika Olehno, for the cute logo
|
30
|
-
* {Rack}[http://rack.rubyforge.org/], {Sequel}[http://sequel.rubyforge.org/], {escape_utils}[https://github.com/brianmario/escape_utils], and {Active Support}[https://github.com/rails/rails/tree/master/activesupport] authors and contributors, for their amazing work
|
31
|
+
* {Rack}[http://rack.rubyforge.org/], {Sequel}[http://sequel.rubyforge.org/], {Bundler}[http://gembundler.com/], {escape_utils}[https://github.com/brianmario/escape_utils], and {Active Support}[https://github.com/rails/rails/tree/master/activesupport] authors and contributors, for their amazing work
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en-US">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title><%! title_view %></title>
|
6
|
+
<link rel="stylesheet" href="/bundle.css" media="screen" />
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
%! view
|
10
|
+
%~ ctx.javascripts.each_key do |js|
|
11
|
+
<script><%= File.read js %></script>
|
12
|
+
%~ end
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
Untitled
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Tanuki::Fetcher::Sequel
|
2
|
+
def initialize(dataset, controller_class)
|
3
|
+
@dataset = dataset
|
4
|
+
@controller_class = controller_class
|
5
|
+
end
|
6
|
+
|
7
|
+
def fetch(md, format)
|
8
|
+
keys = Hash[md.names.map {|name| [name.to_sym, md[name]] }]
|
9
|
+
item = @dataset.filter(keys).first
|
10
|
+
if item
|
11
|
+
{
|
12
|
+
:class => @controller_class,
|
13
|
+
:model => item,
|
14
|
+
:route => format.call(item).to_sym
|
15
|
+
}
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def fetch_all(format)
|
22
|
+
@dataset.each do |item|
|
23
|
+
yield({
|
24
|
+
:class => @controller_class,
|
25
|
+
:model => item,
|
26
|
+
:route => format.call(item).to_sym
|
27
|
+
})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def length
|
32
|
+
@dataset.count
|
33
|
+
end
|
34
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class Tanuki::Manager::Controller
|
2
|
-
end
|
2
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class Tanuki::Manager::Page
|
2
|
-
end
|
2
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class Tanuki::Model::Controller
|
2
|
-
end
|
2
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class Tanuki::Model::Page
|
2
|
-
end
|
2
|
+
end
|
@@ -39,7 +39,7 @@
|
|
39
39
|
<body>
|
40
40
|
<h1>Page not found!</h1>
|
41
41
|
<div>
|
42
|
-
<p>It seems that the page <code><%= ctx.env['REQUEST_URI'] %></code> at <a href="/"><%= ctx.env['HTTP_HOST'] %></a></p>
|
42
|
+
<p>It seems that the page <code><%= ctx.request.env['REQUEST_URI'] %></code> at <a href="/"><%= ctx.request.env['HTTP_HOST'] %></a></p>
|
43
43
|
<ul>
|
44
44
|
<li>has moved,</li>
|
45
45
|
<li>no longer exists,</li>
|
@@ -0,0 +1 @@
|
|
1
|
+
Welcome to Tanuki!
|
@@ -0,0 +1,88 @@
|
|
1
|
+
body {
|
2
|
+
margin: 0;
|
3
|
+
padding: 0;
|
4
|
+
font-family: 'Trebuchet MS', Helvetica, sans-serif;
|
5
|
+
font-size: 11pt;
|
6
|
+
background-color: #f5f4ef;
|
7
|
+
color: #000305;
|
8
|
+
}
|
9
|
+
|
10
|
+
#header {
|
11
|
+
margin: 0 auto;
|
12
|
+
width: 540px;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.top {
|
16
|
+
background-color: #fff;
|
17
|
+
margin: 0 auto 20px auto;
|
18
|
+
padding: 15px 20px 0 20px;
|
19
|
+
width: 540px;
|
20
|
+
border-radius: 10px;
|
21
|
+
-moz-border-radius: 10px;
|
22
|
+
-webkit-border-radius: 10px;
|
23
|
+
}
|
24
|
+
|
25
|
+
h1 {
|
26
|
+
margin: 20px 0;
|
27
|
+
padding: 0;
|
28
|
+
font-size: 22pt;
|
29
|
+
}
|
30
|
+
|
31
|
+
h1 em {
|
32
|
+
display: block;
|
33
|
+
font-style: normal;
|
34
|
+
font-size: 12pt;
|
35
|
+
color: #777a7c;
|
36
|
+
}
|
37
|
+
|
38
|
+
h2 {
|
39
|
+
margin: 0 0 15px 0;
|
40
|
+
padding: 0;
|
41
|
+
font-size: 16pt;
|
42
|
+
}
|
43
|
+
|
44
|
+
#next ol {
|
45
|
+
margin: 0;
|
46
|
+
padding-bottom: 25px;
|
47
|
+
}
|
48
|
+
|
49
|
+
#next li {
|
50
|
+
margin: 0;
|
51
|
+
padding: 0;
|
52
|
+
font-size: 16pt;
|
53
|
+
font-weight: bold;
|
54
|
+
color: #c74451;
|
55
|
+
}
|
56
|
+
|
57
|
+
#next li span {
|
58
|
+
font-size: 11pt;
|
59
|
+
font-weight: normal;
|
60
|
+
color: #000305;
|
61
|
+
}
|
62
|
+
|
63
|
+
code {
|
64
|
+
font-family: 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Menlo, Monaco, Consolas, 'Courier New', monospace;
|
65
|
+
font-size: 10pt;
|
66
|
+
background-color: #fffccc;
|
67
|
+
padding: 1px 3px;
|
68
|
+
}
|
69
|
+
|
70
|
+
#env div {
|
71
|
+
padding-bottom: 25px;
|
72
|
+
}
|
73
|
+
|
74
|
+
#env table {
|
75
|
+
margin: 0;
|
76
|
+
padding: 0;
|
77
|
+
border-collapse: collapse;
|
78
|
+
color: #444;
|
79
|
+
}
|
80
|
+
|
81
|
+
#env table th {
|
82
|
+
text-align: left;
|
83
|
+
}
|
84
|
+
|
85
|
+
#env table td {
|
86
|
+
padding-left: 20px;
|
87
|
+
font-size: 10pt;
|
88
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<div id="header">
|
2
|
+
<h1>It Works! <em>You have been granted one Tanuki.</em></h1>
|
3
|
+
</div>
|
4
|
+
<div class="top" id="next">
|
5
|
+
<h2>What to do next</h2>
|
6
|
+
<div>
|
7
|
+
<p>Here's a few suggestions to get things going:</p>
|
8
|
+
<ol>
|
9
|
+
<li><span>To use a database, describe its contents in <code>schema/user</code>.</span></li>
|
10
|
+
<li><span>To generate models from your schema, run <code>tanuki generate</code>.</span></li>
|
11
|
+
<li><span>To add or edit controllers, navigate to <code>app/user</code>.</span></li>
|
12
|
+
</ol>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<div class="top" id="env">
|
16
|
+
<h2>Your setup</h2>
|
17
|
+
<div><table>
|
18
|
+
<tr><th>Ruby</th><td><%= RUBY_VERSION %>p<%= RUBY_PATCHLEVEL %> (<%= RUBY_RELEASE_DATE %> revision <%= RUBY_REVISION %>) [<%= RUBY_PLATFORM %>]</td></tr>
|
19
|
+
<tr><th>Rack</th><td><%= Rack.version %> (on <%= ctx.request.env['SERVER_SOFTWARE'] %>)</td></tr>
|
20
|
+
<tr><th>Tanuki</th><td><%= Tanuki.version %></td></tr>
|
21
|
+
</table></div>
|
22
|
+
</div>
|
data/bin/tanuki
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
$:.unshift File.expand_path(
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
3
4
|
require 'tanuki/utility'
|
4
5
|
Tanuki::Utility.init if File.basename(__FILE__) == File.basename($0)
|
data/config/common.rb
CHANGED
@@ -2,16 +2,13 @@ load_config :common
|
|
2
2
|
|
3
3
|
# Rack middleware
|
4
4
|
use Rack::Head
|
5
|
-
use Rack::StaticDir,
|
5
|
+
use Rack::StaticDir, @context.public_root
|
6
6
|
|
7
|
-
#
|
8
|
-
set :server, [:thin, :mongrel, :webrick]
|
9
|
-
set :host, '0.0.0.0'
|
10
|
-
set :port, 3000
|
7
|
+
# Environment
|
11
8
|
set :development, false
|
12
9
|
|
13
10
|
# Default controllers
|
14
|
-
set :root_page, ::User::Page::
|
11
|
+
set :root_page, ::User::Page::Home
|
15
12
|
set :missing_page, ::Tanuki::Page::Missing
|
16
13
|
|
17
14
|
# Internationalization
|
data/lib/tanuki.rb
CHANGED
@@ -9,19 +9,20 @@ require 'yaml'
|
|
9
9
|
require 'escape_utils'
|
10
10
|
require 'escape_utils/url/rack'
|
11
11
|
require 'tanuki/version'
|
12
|
+
require 'tanuki/const'
|
12
13
|
require 'tanuki/extensions/module'
|
13
|
-
require 'tanuki/extensions/rack/
|
14
|
-
require 'tanuki/extensions/rack/server'
|
14
|
+
require 'tanuki/extensions/rack/frozen_route'
|
15
15
|
require 'tanuki/extensions/rack/static_dir'
|
16
|
-
require 'tanuki/
|
17
|
-
require 'tanuki/
|
18
|
-
require 'tanuki/behavior/model_behavior'
|
19
|
-
require 'tanuki/behavior/object_behavior'
|
16
|
+
require 'tanuki/base_behavior'
|
17
|
+
require 'tanuki/extensions/sequel/model'
|
20
18
|
require 'tanuki/argument'
|
21
19
|
require 'tanuki/configurator'
|
22
20
|
require 'tanuki/context'
|
23
|
-
require 'tanuki/
|
21
|
+
require 'tanuki/controller'
|
22
|
+
require 'tanuki/css_compressor'
|
24
23
|
require 'tanuki/loader'
|
24
|
+
require 'tanuki/meta_model'
|
25
|
+
require 'tanuki/model_behavior'
|
25
26
|
require 'tanuki/i18n'
|
26
27
|
require 'tanuki/template_compiler'
|
27
28
|
require 'tanuki/application'
|
data/lib/tanuki/application.rb
CHANGED
@@ -1,50 +1,29 @@
|
|
1
1
|
module Tanuki
|
2
2
|
|
3
3
|
# Tanuki::Application is the starting point for all framework applications.
|
4
|
-
# It contains core application functionality like configuration, request
|
4
|
+
# It contains core application functionality like configuration, request
|
5
|
+
# handling and view management.
|
5
6
|
class Application
|
6
7
|
|
7
|
-
|
8
|
+
Loader.context = Context
|
8
9
|
@rack_middleware = []
|
9
10
|
|
10
11
|
class << self
|
11
12
|
|
12
|
-
# Initializes application
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if pwd != default_root
|
23
|
-
@cfg.config_root = File.join(default_root, 'config')
|
24
|
-
@cfg.load_config(([:development, :production].include? env) ? :"#{env}_application" : :common_application)
|
25
|
-
end
|
26
|
-
|
27
|
-
# Configure in application root
|
28
|
-
@cfg.config_root = File.join(pwd, 'config')
|
29
|
-
@cfg.load_config :"#{env}_application", pwd != default_root
|
30
|
-
|
31
|
-
return true
|
32
|
-
rescue NameError => e
|
33
|
-
if e.name =~ /\AA-Z/
|
34
|
-
raise NameError, "missing class or module for constant `#{e.name}'", e.backtrace
|
35
|
-
else
|
36
|
-
raise e
|
37
|
-
end
|
38
|
-
end
|
39
|
-
false
|
13
|
+
# Initializes the application in a given Rack::Builder +builder+.
|
14
|
+
def build(builder)
|
15
|
+
puts %{Calling for Tanuki #{Tanuki.version} in "#{Dir.pwd}"}
|
16
|
+
configure
|
17
|
+
Loader.prepare_for_production unless @cfg.context.development
|
18
|
+
at_exit { puts 'Tanuki ran away!' }
|
19
|
+
configure_middleware(builder)
|
20
|
+
vowel = @environment =~ /\A[aeiou]/
|
21
|
+
puts "A#{'n' if vowel} #{@environment} Tanuki appears!"
|
22
|
+
rack_app
|
40
23
|
end
|
41
24
|
|
42
|
-
#
|
43
|
-
|
44
|
-
@rack_middleware.each {|item| rack_builder.use(item[0], *item[1], &item[2]) }
|
45
|
-
end
|
46
|
-
|
47
|
-
# Removes all occurences of a given +middleware+ from the Rack middleware pipeline.
|
25
|
+
# Removes all occurences of a given +middleware+ from the Rack
|
26
|
+
# middleware pipeline.
|
48
27
|
def discard(middleware)
|
49
28
|
@rack_middleware.delete_if {|item| item[0] == middleware }
|
50
29
|
end
|
@@ -55,21 +34,18 @@ module Tanuki
|
|
55
34
|
@environment ||= nil
|
56
35
|
end
|
57
36
|
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
@context.running_server.run rack_builder.to_app, :Host => @context.host, :Port => @context.port do |server|
|
66
|
-
[:INT, :TERM].each {|sig| trap(sig) { (server.respond_to? :stop!) ? server.stop! : server.stop } }
|
67
|
-
puts "A#{'n' if @environment =~ /\A[aeiou]/} #{@environment} Tanuki appears! Press Ctrl-C to set it free.",
|
68
|
-
"You used #{@context.running_server.name.gsub(/.*::/, '')} at #{@context.host}:#{@context.port}."
|
37
|
+
# Pulls all occurences of a given +middleware+ down to the end
|
38
|
+
# of the Rack middleware pipeline (it would have the lowest priority).
|
39
|
+
def pull_down(middleware)
|
40
|
+
items = @rack_middleware.select {|item| item[0] == middleware }
|
41
|
+
if items
|
42
|
+
@rack_middleware.reject! {|item| item[0] == middleware }
|
43
|
+
items.each {|item| @rack_middleware << item }
|
69
44
|
end
|
70
45
|
end
|
71
46
|
|
72
|
-
# Adds a given +middleware+ with optional +args+ and +block+
|
47
|
+
# Adds a given +middleware+ with optional +args+ and +block+
|
48
|
+
# to the Rack middleware pipeline.
|
73
49
|
def use(middleware, *args, &block)
|
74
50
|
@rack_middleware << [middleware, args, block]
|
75
51
|
end
|
@@ -90,70 +66,121 @@ module Tanuki
|
|
90
66
|
# <%_escape escaped_view %>
|
91
67
|
# <%_printf('<div>%s</div>') formatted_view %>
|
92
68
|
def visitor(sym, &block)
|
93
|
-
BaseBehavior.instance_eval
|
69
|
+
BaseBehavior.instance_eval do
|
70
|
+
define_method "#{sym}_visitor".to_sym, &block
|
71
|
+
end
|
94
72
|
end
|
95
73
|
|
96
74
|
private
|
97
75
|
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
76
|
+
# Initializes application settings using configuration
|
77
|
+
# for the current Rack environment.
|
78
|
+
# These include settings for server, context, and middleware.
|
79
|
+
def configure
|
80
|
+
@environment = ENV['RACK_ENV'].to_sym
|
81
|
+
default_root = File.expand_path('../../..', __FILE__)
|
82
|
+
@cfg = Configurator.new(Context, pwd = Dir.pwd)
|
83
|
+
env_config = :"#{@environment}_application"
|
84
|
+
|
85
|
+
# Configure in default root (e.g. gem root)
|
86
|
+
if pwd != default_root
|
87
|
+
@cfg.config_root = File.join(default_root, 'config')
|
88
|
+
if [:development, :production].include? @environment
|
89
|
+
default_config = env_config
|
90
|
+
else
|
91
|
+
default_config = :common_application
|
105
92
|
end
|
93
|
+
@cfg.load_config default_config
|
106
94
|
end
|
107
|
-
|
95
|
+
|
96
|
+
# Configure in application root
|
97
|
+
@cfg.config_root = File.join(pwd, 'config')
|
98
|
+
if @cfg.config_file? env_config
|
99
|
+
@cfg.load_config env_config, pwd != default_root
|
100
|
+
elsif @cfg.config_file? :common_application
|
101
|
+
@cfg.load_config :common_application
|
102
|
+
end
|
103
|
+
|
104
|
+
self
|
105
|
+
rescue NameError => e
|
106
|
+
raise e unless e.name =~ /\AA-Z/
|
107
|
+
message = "missing class or module for constant `#{e.name}'"
|
108
|
+
raise NameError, message, e.backtrace
|
108
109
|
end
|
109
110
|
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
|
111
|
+
# Add utilized middleware to a given Rack::Builder instance
|
112
|
+
# +rack_builder+.
|
113
|
+
def configure_middleware(rack_builder)
|
114
|
+
@rack_middleware.each do |item|
|
115
|
+
rack_builder.use item[0], *item[1], &item[2]
|
116
|
+
end
|
114
117
|
end
|
115
118
|
|
116
119
|
# Returns a Rack app block for Rack::Builder.
|
117
|
-
# This block is passed a request environment
|
120
|
+
# This block is passed a request environment
|
121
|
+
# and returns and array of three elements:
|
118
122
|
# * a response status code,
|
119
123
|
# * a hash of headers,
|
120
124
|
# * an iterable body object.
|
121
125
|
# It is run on each request.
|
122
126
|
def rack_app
|
123
|
-
ctx = @context
|
124
127
|
proc do |env|
|
125
|
-
request_ctx = ctx.child
|
126
|
-
request_ctx.templates = {}
|
127
128
|
|
128
129
|
# If there are trailing slashes in path, don't dispatch
|
129
|
-
|
130
|
+
path_info = env[Const::PATH_INFO]
|
131
|
+
if match = path_info.match(Const::TRAILING_SLASH)
|
130
132
|
|
131
133
|
# Remove trailing slash in the path and redirect
|
132
134
|
loc = match[1]
|
133
|
-
|
134
|
-
|
135
|
+
query_string = env[Const::QUERY_STRING]
|
136
|
+
loc << "?#{query_string}" unless query_string.empty?
|
137
|
+
[
|
138
|
+
301,
|
139
|
+
{
|
140
|
+
Const::LOCATION => loc,
|
141
|
+
Const::CONTENT_TYPE => Const::MIME_TEXT_HTML
|
142
|
+
},
|
143
|
+
Const::EMPTY_ARRAY
|
144
|
+
]
|
135
145
|
|
136
146
|
else
|
147
|
+
ctx = Context.child
|
148
|
+
ctx.templates = {}
|
149
|
+
ctx.resources = {}
|
150
|
+
ctx.javascripts = {}
|
137
151
|
|
138
152
|
# Dispatch controller chain for the current path
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
153
|
+
Loader.refresh_css if ctx.development
|
154
|
+
ctx.request = Rack::Request.new(env)
|
155
|
+
resp = ctx.response = Rack::Response.new(
|
156
|
+
[],
|
157
|
+
200,
|
158
|
+
{Const::CONTENT_TYPE => Const::MIME_TEXT_HTML}
|
159
|
+
)
|
160
|
+
template = nil
|
161
|
+
catch :halt do
|
162
|
+
template = ::Tanuki::Controller.dispatch(
|
163
|
+
ctx,
|
164
|
+
Context.i18n ? ::Tanuki::I18n : Context.root_page,
|
165
|
+
Rack::Utils.unescape(path_info).force_encoding(Const::UTF_8)
|
166
|
+
)
|
167
|
+
end
|
168
|
+
if template &&
|
169
|
+
template.is_a?(Method) &&
|
170
|
+
template.receiver.is_a?(BaseBehavior) &&
|
171
|
+
template.name =~ Const::VIEW_METHOD
|
172
|
+
then
|
173
|
+
resp.finish do |resp|
|
174
|
+
template.call.call(proc {|s| resp.write s }, ctx)
|
175
|
+
end
|
149
176
|
else
|
150
|
-
|
177
|
+
resp.finish
|
151
178
|
end
|
152
179
|
|
153
180
|
end # if
|
154
181
|
|
155
|
-
end
|
156
|
-
end
|
182
|
+
end # proc
|
183
|
+
end # rack_app
|
157
184
|
|
158
185
|
end # class << self
|
159
186
|
|