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.
Files changed (63) hide show
  1. data/README.rdoc +5 -4
  2. data/app/tanuki/controller/{link.thtml → controller.link.thtml} +0 -0
  3. data/app/tanuki/controller/controller.page.thtml +14 -0
  4. data/app/tanuki/controller/controller.rb +1 -2
  5. data/app/tanuki/controller/controller.title.ttxt +1 -0
  6. data/app/tanuki/controller/controller.view.thtml +3 -0
  7. data/app/tanuki/fetcher/sequel/sequel.rb +34 -0
  8. data/app/tanuki/manager/controller/controller.rb +1 -1
  9. data/app/tanuki/manager/page/page.rb +1 -1
  10. data/app/tanuki/meta_model/{manager.ttxt → meta_model.manager.ttxt} +0 -0
  11. data/app/tanuki/meta_model/{manager_base.ttxt → meta_model.manager_base.ttxt} +0 -0
  12. data/app/tanuki/meta_model/{model.ttxt → meta_model.model.ttxt} +0 -0
  13. data/app/tanuki/meta_model/{model_base.ttxt → meta_model.model_base.ttxt} +0 -0
  14. data/app/tanuki/meta_model/meta_model.rb +1 -2
  15. data/app/tanuki/model/controller/controller.rb +1 -1
  16. data/app/tanuki/model/page/page.rb +1 -1
  17. data/app/tanuki/page/missing/{default.thtml → missing.page.thtml} +1 -1
  18. data/app/tanuki/page/missing/missing.rb +3 -2
  19. data/app/user/page/home/home.rb +2 -0
  20. data/app/user/page/home/home.title.thtml +1 -0
  21. data/app/user/page/home/home.view.css +88 -0
  22. data/app/user/page/home/home.view.thtml +22 -0
  23. data/bin/tanuki +2 -1
  24. data/config/common.rb +1 -0
  25. data/config/common_application.rb +3 -6
  26. data/config/development_application.rb +0 -3
  27. data/lib/tanuki.rb +8 -7
  28. data/lib/tanuki/application.rb +108 -81
  29. data/lib/tanuki/argument.rb +10 -5
  30. data/lib/tanuki/argument/integer_range.rb +4 -2
  31. data/lib/tanuki/{behavior/object_behavior.rb → base_behavior.rb} +21 -4
  32. data/lib/tanuki/configurator.rb +20 -8
  33. data/lib/tanuki/const.rb +32 -0
  34. data/lib/tanuki/context.rb +18 -7
  35. data/lib/tanuki/controller.rb +517 -0
  36. data/lib/tanuki/css_compressor.rb +50 -0
  37. data/lib/tanuki/extensions/module.rb +21 -5
  38. data/lib/tanuki/extensions/rack/frozen_route.rb +35 -0
  39. data/lib/tanuki/extensions/rack/static_dir.rb +1 -1
  40. data/lib/tanuki/extensions/sequel/model.rb +7 -0
  41. data/lib/tanuki/i18n.rb +8 -6
  42. data/lib/tanuki/loader.rb +166 -33
  43. data/lib/tanuki/meta_model.rb +176 -0
  44. data/lib/tanuki/{behavior/model_behavior.rb → model_behavior.rb} +7 -3
  45. data/lib/tanuki/model_generator.rb +49 -29
  46. data/lib/tanuki/template_compiler.rb +72 -41
  47. data/lib/tanuki/utility.rb +11 -4
  48. data/lib/tanuki/utility/create.rb +52 -11
  49. data/lib/tanuki/utility/generate.rb +16 -10
  50. data/lib/tanuki/utility/version.rb +1 -1
  51. data/lib/tanuki/version.rb +7 -2
  52. metadata +50 -66
  53. data/app/tanuki/controller/default.thtml +0 -5
  54. data/app/tanuki/controller/index.thtml +0 -1
  55. data/app/user/page/index/default.thtml +0 -121
  56. data/app/user/page/index/index.rb +0 -2
  57. data/config/test_application.rb +0 -2
  58. data/lib/tanuki/behavior/controller_behavior.rb +0 -366
  59. data/lib/tanuki/behavior/meta_model_behavior.rb +0 -160
  60. data/lib/tanuki/extensions/rack/builder.rb +0 -26
  61. data/lib/tanuki/extensions/rack/server.rb +0 -18
  62. data/lib/tanuki/launcher.rb +0 -21
  63. data/lib/tanuki/utility/server.rb +0 -23
@@ -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
- tanuki> create test
16
- tanuki> server
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
@@ -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>
@@ -1,3 +1,2 @@
1
- class Tanuki::Controller < Tanuki::Base
2
- include Tanuki::ControllerBehavior
1
+ class Tanuki::Controller
3
2
  end
@@ -0,0 +1,3 @@
1
+ %~ if visual_child
2
+ %! visual_child.view
3
+ %~ end
@@ -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
@@ -1,3 +1,2 @@
1
- class Tanuki::MetaModel < Tanuki::Base
2
- include Tanuki::MetaModelBehavior
1
+ class Tanuki::MetaModel
3
2
  end
@@ -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>
@@ -3,7 +3,8 @@ class Tanuki::Page::Missing < Tanuki::Controller
3
3
  nil
4
4
  end
5
5
 
6
- def result_type
7
- :not_found
6
+ def get # TODO: add other request methods
7
+ status 404
8
+ super
8
9
  end
9
10
  end
@@ -0,0 +1,2 @@
1
+ class User::Page::Home < Tanuki::Controller
2
+ end
@@ -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(File.join('..', '..', 'lib'), __FILE__)
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)
@@ -2,6 +2,7 @@
2
2
  set :app_root, proc { File.join(root, 'app') }
3
3
  set :gen_root, proc { File.join(root, 'gen') }
4
4
  set :schema_root, proc { File.join(root, 'schema') }
5
+ set :public_root, proc { File.join(root, 'public') }
5
6
 
6
7
  # Cache
7
8
  set :templates, {}
@@ -2,16 +2,13 @@ load_config :common
2
2
 
3
3
  # Rack middleware
4
4
  use Rack::Head
5
- use Rack::StaticDir, 'public'
5
+ use Rack::StaticDir, @context.public_root
6
6
 
7
- # Server
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::Index
11
+ set :root_page, ::User::Page::Home
15
12
  set :missing_page, ::Tanuki::Page::Missing
16
13
 
17
14
  # Internationalization
@@ -2,7 +2,4 @@ load_config :common_application
2
2
  set :development, true
3
3
 
4
4
  # Rack middleware
5
- use Rack::CommonLogger
6
- use Rack::Lint
7
5
  use Rack::Reloader, 0
8
- use Rack::ShowExceptions
@@ -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/builder'
14
- require 'tanuki/extensions/rack/server'
14
+ require 'tanuki/extensions/rack/frozen_route'
15
15
  require 'tanuki/extensions/rack/static_dir'
16
- require 'tanuki/behavior/controller_behavior'
17
- require 'tanuki/behavior/meta_model_behavior'
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/launcher'
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'
@@ -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 handling and view management.
4
+ # It contains core application functionality like configuration, request
5
+ # handling and view management.
5
6
  class Application
6
7
 
7
- @context = (Loader.context = Context).child
8
+ Loader.context = Context
8
9
  @rack_middleware = []
9
10
 
10
11
  class << self
11
12
 
12
- # Initializes application settings using configuration for environment +env+.
13
- # These include settings for server, context, and middleware.
14
- # Returns true, if configuration is successful.
15
- def configure(env)
16
- @environment = env
17
- begin
18
- default_root = File.expand_path(File.join('..', '..', '..'), __FILE__)
19
- @cfg = Configurator.new(Context, pwd = Dir.pwd)
20
-
21
- # Configure in default root (e.g. gem root)
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
- # Add utilized middleware to a given Rack::Builder instance +rack_builder+.
43
- def configure_middleware(rack_builder)
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
- # Runs the application with current settings.
59
- def run
60
- configure_middleware(rack_builder = Rack::Builder.new)
61
- rack_builder.run(rack_app)
62
-
63
- # Choose and start a Rack handler
64
- @context.running_server = available_server
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+ to the Rack middleware pipeline.
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 { define_method "#{sym}_visitor".to_sym, &block }
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
- # Returns the first available server from a server list in the current context.
99
- def available_server
100
- @context.server.each do |server_name|
101
- begin
102
- return Rack::Handler.get(server_name.downcase)
103
- rescue LoadError
104
- rescue NameError
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
- raise "servers #{@context.server.join(', ')} not found"
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
- # Returns an array of template outputs for controller +ctrl+ in context +request_ctx+.
111
- def build_body(ctrl, request_ctx)
112
- arr = []
113
- Launcher.new(ctrl, request_ctx).each &proc {|out| arr << out.to_s }
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 and returns and array of three elements:
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
- if match = env['PATH_INFO'].match(/^(.+)(?<!\$)\/$/)
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
- loc << "?#{env['QUERY_STRING']}" unless env['QUERY_STRING'].empty?
134
- [301, {'Location' => loc, 'Content-Type' => 'text/html; charset=utf-8'}, []]
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
- request_ctx.env = env
140
- result = ::Tanuki::ControllerBehavior.dispatch(request_ctx, ctx.i18n ? ::Tanuki::I18n : ctx.root_page,
141
- Rack::Utils.unescape(env['PATH_INFO']).force_encoding('UTF-8'))
142
-
143
- # Handle dispatch result
144
- case result[:type]
145
- when :redirect then
146
- [302, {'Location' => result[:location], 'Content-Type' => 'text/html; charset=utf-8'}, []]
147
- when :page then
148
- [200, {'Content-Type' => 'text/html; charset=utf-8'}, build_body(result[:controller], request_ctx)]
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
- [404, {'Content-Type' => 'text/html; charset=utf-8'}, build_body(result[:controller], request_ctx)]
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