ramaze 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. data/bin/ramaze +58 -26
  2. data/doc/AUTHORS +2 -0
  3. data/doc/CHANGELOG +401 -0
  4. data/doc/README +14 -9
  5. data/doc/README.html +737 -0
  6. data/doc/TODO +14 -14
  7. data/doc/changes.txt +401 -0
  8. data/doc/changes.xml +401 -0
  9. data/doc/meta/announcement.txt +28 -15
  10. data/doc/meta/configuration.txt +3 -3
  11. data/doc/meta/internals.txt +2 -2
  12. data/doc/meta/users.kml +62 -0
  13. data/doc/readme_chunks/examples.txt +1 -1
  14. data/doc/readme_chunks/features.txt +13 -8
  15. data/doc/tutorial/todolist.html +2 -2
  16. data/doc/tutorial/todolist.mkd +2 -2
  17. data/examples/blog/README +3 -0
  18. data/examples/blog/spec/blog.rb +101 -0
  19. data/examples/blog/{main.rb → start.rb} +0 -0
  20. data/examples/caching.rb +16 -5
  21. data/examples/layout.rb +41 -0
  22. data/examples/templates/template_amrita2.rb +1 -1
  23. data/examples/templates/template_erubis.rb +1 -1
  24. data/examples/templates/template_ezamar.rb +1 -1
  25. data/examples/templates/template_haml.rb +1 -1
  26. data/examples/templates/template_liquid.rb +1 -1
  27. data/examples/templates/template_markaby.rb +1 -1
  28. data/examples/templates/template_remarkably.rb +1 -1
  29. data/examples/todolist/README +1 -0
  30. data/{spec/examples → examples/todolist/spec}/todolist.rb +3 -3
  31. data/examples/todolist/{main.rb → start.rb} +0 -0
  32. data/examples/whywiki/{main.rb → start.rb} +0 -0
  33. data/examples/wiktacular/README +2 -0
  34. data/examples/wiktacular/spec/wiktacular.rb +146 -0
  35. data/examples/wiktacular/src/controller.rb +11 -0
  36. data/examples/wiktacular/src/model.rb +5 -1
  37. data/examples/wiktacular/{main.rb → start.rb} +0 -1
  38. data/examples/wiktacular/template/edit.xhtml +1 -2
  39. data/examples/wiktacular/template/html_layout.xhtml +27 -0
  40. data/examples/wiktacular/template/index.xhtml +8 -10
  41. data/examples/wiktacular/template/new.xhtml +1 -2
  42. data/lib/proto/{main.rb → start.rb} +0 -0
  43. data/lib/proto/template/index.xhtml +1 -1
  44. data/lib/ramaze/action/render.rb +58 -4
  45. data/lib/ramaze/action.rb +20 -0
  46. data/lib/ramaze/adapter/cgi.rb +7 -4
  47. data/lib/ramaze/adapter/fcgi.rb +6 -4
  48. data/lib/ramaze/adapter/mongrel.rb +4 -0
  49. data/lib/ramaze/adapter/webrick.rb +20 -9
  50. data/lib/ramaze/adapter.rb +3 -1
  51. data/lib/ramaze/cache/memcached.rb +2 -26
  52. data/lib/ramaze/cache.rb +8 -4
  53. data/lib/ramaze/controller/resolve.rb +26 -8
  54. data/lib/ramaze/controller.rb +44 -7
  55. data/lib/ramaze/dispatcher/action.rb +5 -1
  56. data/lib/ramaze/dispatcher/directory.rb +115 -0
  57. data/lib/ramaze/dispatcher/error.rb +19 -5
  58. data/lib/ramaze/dispatcher/file.rb +2 -2
  59. data/lib/ramaze/dispatcher.rb +52 -39
  60. data/lib/ramaze/global/dsl.rb +3 -2
  61. data/lib/ramaze/global/globalstruct.rb +26 -4
  62. data/lib/ramaze/global.rb +20 -11
  63. data/lib/ramaze/helper/aspect.rb +29 -11
  64. data/lib/ramaze/helper/auth.rb +2 -2
  65. data/lib/ramaze/helper/cache.rb +2 -0
  66. data/lib/ramaze/helper/identity.rb +21 -6
  67. data/lib/ramaze/helper/link.rb +1 -1
  68. data/lib/ramaze/helper/pager.rb +158 -100
  69. data/lib/ramaze/helper/partial.rb +22 -0
  70. data/lib/ramaze/helper/redirect.rb +1 -2
  71. data/lib/ramaze/helper/stack.rb +1 -1
  72. data/lib/ramaze/inform/informer.rb +20 -0
  73. data/lib/ramaze/inform/syslog.rb +5 -0
  74. data/lib/ramaze/snippets/kernel/__dir__.rb +21 -0
  75. data/lib/ramaze/snippets/kernel/aquire.rb +22 -12
  76. data/lib/ramaze/snippets/numeric/human_readable_filesize_format.rb +33 -0
  77. data/lib/ramaze/snippets/ramaze/caller_lines.rb +1 -1
  78. data/lib/ramaze/snippets/struct/values_at.rb +11 -4
  79. data/lib/ramaze/sourcereload.rb +29 -1
  80. data/{spec → lib/ramaze/spec}/helper/context.rb +0 -0
  81. data/{spec → lib/ramaze/spec}/helper/layout.rb +1 -1
  82. data/{spec → lib/ramaze/spec}/helper/minimal.rb +0 -0
  83. data/{spec → lib/ramaze/spec}/helper/mock_http.rb +0 -0
  84. data/{spec → lib/ramaze/spec}/helper/requester.rb +0 -0
  85. data/{spec → lib/ramaze/spec}/helper/simple_http.rb +0 -0
  86. data/{spec → lib/ramaze/spec}/helper/wrap.rb +0 -0
  87. data/lib/ramaze/spec/helper.rb +60 -0
  88. data/lib/ramaze/store/default.rb +3 -0
  89. data/lib/ramaze/template/ezamar/render_partial.rb +3 -0
  90. data/lib/ramaze/template/sass.rb +45 -0
  91. data/lib/ramaze/template.rb +1 -1
  92. data/lib/ramaze/tool/create.rb +5 -5
  93. data/lib/ramaze/tool/localize.rb +26 -5
  94. data/lib/ramaze/tool/mime.rb +7 -0
  95. data/lib/ramaze/trinity/response.rb +15 -0
  96. data/lib/ramaze/trinity/session.rb +1 -1
  97. data/lib/ramaze/version.rb +1 -1
  98. data/lib/ramaze.rb +5 -0
  99. data/rake_tasks/conf.rake +4 -4
  100. data/rake_tasks/maintaince.rake +12 -7
  101. data/rake_tasks/spec.rake +7 -4
  102. data/spec/examples/caching.rb +6 -8
  103. data/spec/helper.rb +3 -60
  104. data/spec/ramaze/action/basics.rb +17 -0
  105. data/spec/ramaze/action/cache.rb +28 -0
  106. data/spec/ramaze/action/layout.rb +110 -0
  107. data/spec/ramaze/action/render.rb +14 -0
  108. data/spec/ramaze/action/template/bar.xhtml +1 -0
  109. data/spec/ramaze/action/template/other_wrapper.xhtml +1 -0
  110. data/spec/ramaze/action/template/single_wrapper.xhtml +1 -0
  111. data/spec/ramaze/controller/template/edit/content.xhtml +1 -0
  112. data/spec/ramaze/controller/template/edit.xhtml +1 -0
  113. data/spec/ramaze/controller/template_resolving.rb +2 -2
  114. data/spec/ramaze/dispatcher/directory.rb +53 -0
  115. data/spec/ramaze/dispatcher/file.rb +0 -3
  116. data/spec/ramaze/error.rb +17 -2
  117. data/spec/ramaze/helper/aspect.rb +14 -20
  118. data/spec/ramaze/helper/pager.rb +83 -1
  119. data/spec/ramaze/helper/partial.rb +1 -1
  120. data/spec/ramaze/helper/template/test_template.xhtml +1 -0
  121. data/spec/ramaze/inform/informer.rb +37 -5
  122. data/spec/ramaze/localize.rb +1 -1
  123. data/spec/ramaze/template/haml.rb +5 -5
  124. data/spec/ramaze/template/sass/file.css.sass +5 -0
  125. data/spec/ramaze/template/sass.rb +46 -0
  126. data/spec/ramaze/template.rb +1 -1
  127. data/spec/ramaze/trinity/session.rb +27 -0
  128. data/spec/snippets/kernel/__dir__.rb +8 -0
  129. data/spec/snippets/kernel/aquire.rb +71 -0
  130. data/spec/snippets/kernel/constant.rb +27 -0
  131. data/spec/snippets/numeric/human_readable_filesize_format.rb +11 -0
  132. data/spec/snippets/ramaze/caller_info.rb +39 -0
  133. data/spec/snippets/ramaze/caller_lines.rb +27 -0
  134. data/spec/snippets/string/DIVIDE.rb +18 -0
  135. data/spec/snippets/string/camel_case.rb +25 -0
  136. data/spec/snippets/string/color.rb +11 -0
  137. data/spec/snippets/string/snake_case.rb +17 -0
  138. data/spec/snippets/struct/fill.rb +27 -0
  139. data/spec/snippets/struct/values_at.rb +39 -0
  140. metadata +71 -31
  141. data/examples/todolist/todolist.db +0 -5
  142. data/examples/wiktacular/src/page.rb +0 -66
  143. data/lib/ramaze/helper/feed.rb +0 -135
  144. data/lib/ramaze/helper/form.rb +0 -204
  145. data/lib/ramaze/snippets/openstruct/temp.rb +0 -13
  146. data/lib/ramaze/store/yaml.rb +0 -170
  147. data/spec/ramaze/helper/feed.rb +0 -127
  148. data/spec/ramaze/helper/form.rb +0 -146
  149. data/spec/ramaze/store/yaml.rb +0 -76
data/lib/ramaze/action.rb CHANGED
@@ -101,6 +101,26 @@ module Ramaze
101
101
  self[:binding] ||= instance.instance_eval{ binding }
102
102
  end
103
103
 
104
+ def name
105
+ File.basename((self[:method] || self[:template]).to_s).split('.').first
106
+ end
107
+
108
+ # TODO: find good names for this method.
109
+
110
+ def basepath
111
+ @basepath ||= "#{controller.mapping}/#{name}".gsub(/^\/+/, '/')
112
+ end
113
+
114
+ # TODO: find good names for this method.
115
+ def fullpath
116
+ "#{path}/#{params.join('/')}".gsub(/^\/+/, '/')
117
+ end
118
+
119
+ # TODO: find good names for this method.
120
+ def extended_path
121
+ @extended_path ||= File.join(path, *params)
122
+ end
123
+
104
124
  # Hook for AspectHelper
105
125
 
106
126
  def before_process
@@ -4,15 +4,18 @@
4
4
  require 'ramaze/adapter'
5
5
 
6
6
  module Ramaze::Adapter
7
+
8
+ # Our CGI adapter acts as wrapper for the Rack::Handler::CGI.
7
9
  class Cgi < Base
8
10
  class << self
9
- def start host, ports
11
+
12
+ # start CGI in a new thread, host and port parameter are only taken
13
+ # to make it compatible with other adapters but have no influence and
14
+ # can be omitted
15
+ def start host = nil, ports = nil
10
16
  global = Ramaze::Global
11
17
  global.inform_to = :stderr if global.inform_to == $stdout
12
- run_server
13
- end
14
18
 
15
- def run_server
16
19
  Thread.new do
17
20
  Thread.current[:task] = :cgi
18
21
  Rack::Handler::CGI.run(self)
@@ -4,13 +4,15 @@
4
4
  require 'ramaze/adapter'
5
5
 
6
6
  module Ramaze::Adapter
7
+
8
+ # Our Fcgi adapter acts as wrapper for the Rack::Handler::FastCGI.
7
9
  class Fcgi < Base
8
10
  class << self
9
- def start host, ports
10
- run_server
11
- end
12
11
 
13
- def run_server
12
+ # start FastCGI in a new thread, host and port parameter are only taken
13
+ # to make it compatible with other adapters but have no influence and
14
+ # can be omitted
15
+ def start host = nil, ports = nil
14
16
  Thread.new do
15
17
  Thread.current[:task] = :cgi
16
18
  Rack::Handler::FastCGI.run(self)
@@ -16,8 +16,12 @@ module Ramaze
16
16
  require 'rack/handler/mongrel'
17
17
 
18
18
  module Adapter
19
+
20
+ # Our Mongrel adapter acts as wrapper for the Rack::Handler::Mongrel.
19
21
  class Mongrel < Base
20
22
  class << self
23
+
24
+ # start server on given host and port.
21
25
  def run_server host, port
22
26
  server = ::Mongrel::HttpServer.new(host, port)
23
27
  server.register('/', ::Rack::Handler::Mongrel.new(self))
@@ -5,19 +5,14 @@ require 'ramaze/adapter'
5
5
  require 'webrick'
6
6
  require 'rack/handler/webrick'
7
7
 
8
- module WEBrick
9
- module HTTPServlet
10
- class ProcHandler
11
- alias do_PUT do_GET
12
- alias do_DELETE do_GET
13
- end
14
- end
15
- end
16
-
17
8
  module Ramaze
18
9
  module Adapter
10
+
11
+ # Our WEBrick adapter acts as wrapper for the Rack::Handler::WEBrick.
19
12
  class WEBrick < Base
20
13
  class << self
14
+
15
+ # start server on given host and port, see below for possible options.
21
16
  def run_server host, port, options = {}
22
17
  options = {
23
18
  :Port => port,
@@ -41,3 +36,19 @@ module Ramaze
41
36
  end
42
37
  end
43
38
  end
39
+
40
+ # Extending on WEBrick module
41
+ module WEBrick
42
+
43
+ # Extending on HTTPServlet
44
+ module HTTPServlet
45
+
46
+ # Extending on ProcHandler
47
+ #
48
+ # We alias PUT to GET and DELETE to GET so WEBrick handles them as well.
49
+ class ProcHandler
50
+ alias do_PUT do_GET
51
+ alias do_DELETE do_GET
52
+ end
53
+ end
54
+ end
@@ -109,7 +109,9 @@ module Ramaze
109
109
 
110
110
  def test_connection host, port
111
111
  Timeout.timeout(1) do
112
- TCPServer.open(host, port){ true }
112
+ testsock = TCPServer.new(host, port)
113
+ testsock.close
114
+ true
113
115
  end
114
116
  rescue => ex
115
117
  Inform.error(ex)
@@ -62,33 +62,9 @@ module Ramaze
62
62
  def values_at(*keys)
63
63
  get_multi(*keys).values_at(*keys)
64
64
  end
65
- end
66
- end
67
-
68
- # add the MemCache#clear method
69
-
70
- class MemCache
71
-
72
- # MemCache.clear sends 'flush_all' command to all registered MemCache
73
- # servers.
74
-
75
- def clear
76
- raise MemCacheError, "Update of readonly cache" if @readonly
77
-
78
- @servers.each do |server|
79
- server.flush_all
80
- end
81
- end
82
-
83
- # implements the flushing of MemCache server. Flushes a single server,
84
- # MemCache#clear can be used for clearing out all MemCache servers.
85
-
86
- class Server
87
-
88
- # Serverside implementation of the #clear functionality for MemCache
89
65
 
90
- def flush_all
91
- socket.write "flush_all\r\n"
66
+ def clear
67
+ @cache.flush_all
92
68
  end
93
69
  end
94
70
  end
data/lib/ramaze/cache.rb CHANGED
@@ -12,6 +12,8 @@ module Ramaze
12
12
 
13
13
  class Cache
14
14
  include Enumerable
15
+
16
+ # Holds all the instances of Cache that are being added.
15
17
  CACHES = {} unless defined?(CACHES)
16
18
 
17
19
  attr_accessor :cache
@@ -47,33 +49,35 @@ module Ramaze
47
49
  end
48
50
 
49
51
  # Initializes the cache, defined by Global.cache
50
-
51
52
  def initialize(cache = Global.cache)
52
53
  @cache = cache.new
53
54
  end
54
55
 
56
+ # Get key.
55
57
  def [](key)
56
58
  @cache["#{@cache_name}:#{key}"]
57
59
  end
58
60
 
61
+ # Set key to value.
59
62
  def []=(key, value)
60
63
  @cache["#{@cache_name}:#{key}"] = value
61
64
  end
62
65
 
63
66
  # deletes the keys of each argument passed from Cache instance.
64
-
65
67
  def delete(*args)
66
68
  args.each do |arg|
67
69
  @cache.delete("#{@cache_name}:#{arg}")
68
70
  end
69
71
  end
70
72
 
73
+ # Empty this cache
71
74
  def clear
72
75
  @cache.clear
73
76
  end
74
77
 
75
- def values_at(*args)
76
- @cache.values_at(*args.map {|key| "#{@cache_name}:#{key}" })
78
+ # Answers with value for each key.
79
+ def values_at(*keys)
80
+ @cache.values_at(*keys.map {|key| "#{@cache_name}:#{key}" })
77
81
  end
78
82
  end
79
83
  end
@@ -15,7 +15,7 @@ module Ramaze
15
15
  def resolve(path)
16
16
  if found = Cache.resolved[path]
17
17
  if found.respond_to?(:relaxed_hash)
18
- return found
18
+ return found.dup
19
19
  else
20
20
  Inform.warn("Found faulty `#{path}' in Cache.resolved, deleting it for sanity.")
21
21
  Cache.resolved.delete path
@@ -39,7 +39,10 @@ module Ramaze
39
39
 
40
40
  valid_action = (action.method or (params.empty? && template))
41
41
 
42
- return Cache.resolved[path] = action if valid_action
42
+ if valid_action
43
+ Cache.resolved[path] = action
44
+ return action.dup
45
+ end
43
46
  end
44
47
  end
45
48
 
@@ -47,6 +50,8 @@ module Ramaze
47
50
  raise_no_controller(path)
48
51
  end
49
52
 
53
+ # Try to produce an Action from the given path and paremters with the
54
+ # appropiate template if one exists.
50
55
  def resolve_action(path, *parameter)
51
56
  path, parameter = path.to_s, parameter.map(&:to_s)
52
57
  if alternate_template = trait["#{path}_template"]
@@ -67,22 +72,30 @@ module Ramaze
67
72
  :controller => self
68
73
  end
69
74
 
70
- def resolve_template(action)
71
- action = action.to_s
72
- action_converted = action.split('__').inject{|s,v| s/v}
73
- actions = [action, action_converted].compact
75
+ # Search the #template_paths for a fitting template for path.
76
+ # Only the first found possibility for the generated glob is returned.
77
+ def resolve_template(path)
78
+ path = path.to_s
79
+ path_converted = path.split('__').inject{|s,v| s/v}
80
+ possible_paths = [path, path_converted].compact
74
81
 
75
- paths = template_paths.map{|pa| actions.map{|a| pa/a } }.flatten.uniq
82
+ paths = template_paths.map{|pa| possible_paths.map{|a| pa/a } }.flatten.uniq
76
83
  glob = "{#{paths.join(',')}}.{#{extension_order.join(',')}}"
77
84
 
78
85
  Dir[glob].first
79
86
  end
80
87
 
88
+ # Composes an array with the template-paths to look up in the right order.
89
+ # Usually this is composed of Global.template_root and the mapping of the
90
+ # controller and a second element for Global.public_root, which makes
91
+ # it possible to convert CSS on the fly and things like that.
92
+
81
93
  def template_paths
82
94
  @template_root ||= Global.template_root / Global.mapping.invert[self]
83
95
  [ @template_root, Global.public_root ].compact
84
96
  end
85
97
 
98
+ # Based on methodname and arity, tries to find the right method on current controller.
86
99
  def resolve_method(name, *params)
87
100
  if method = action_methods.delete(name)
88
101
  arity = instance_method(method).arity
@@ -93,6 +106,7 @@ module Ramaze
93
106
  return nil, []
94
107
  end
95
108
 
109
+ # methodnames that may be used for current controller.
96
110
  def action_methods
97
111
  exclude = Controller.trait[:exclude_action_modules]
98
112
 
@@ -102,6 +116,7 @@ module Ramaze
102
116
  meths - ancs.map(&:to_s)
103
117
  end
104
118
 
119
+ # Generate all possible permutations for given path.
105
120
  def pattern_for(path)
106
121
  atoms = path.split('/').grep(/\S/)
107
122
  atoms.unshift('')
@@ -129,6 +144,9 @@ module Ramaze
129
144
  patterns.reverse!
130
145
  end
131
146
 
147
+ # Uses custom defined engines and all available engines and throws it
148
+ # against the extensions for the template to find the most likely
149
+ # templating-engine to use ordered by priority and likelyhood.
132
150
  def extension_order
133
151
  t_extensions = Template::ENGINES
134
152
  engine = trait[:engine]
@@ -146,7 +164,7 @@ module Ramaze
146
164
  # Raises Ramaze::Error::NoAction
147
165
 
148
166
  def raise_no_action(controller, path)
149
- Thread.current[:failed_controller] = controller
167
+ Thread.current[:controller] = controller
150
168
  raise Ramaze::Error::NoAction, "No Action found for `#{path}' on #{controller}"
151
169
  end
152
170
  end
@@ -43,7 +43,12 @@ module Ramaze
43
43
 
44
44
  def inherited controller
45
45
  controller.trait :actions_cached => Set.new
46
+ controller.trait :layout => {:all => nil, :deny => Set.new}
46
47
  Global.controllers << controller
48
+ if map = controller.mapping
49
+ Inform.debug("mapping #{map} => #{controller}")
50
+ Global.mapping[map] ||= controller
51
+ end
47
52
  end
48
53
 
49
54
  # called from Ramaze.startup, adds Cache.actions and Cache.patterns, walks
@@ -52,13 +57,9 @@ module Ramaze
52
57
 
53
58
  def startup options = {}
54
59
  Inform.debug("found Controllers: #{Global.controllers.inspect}")
55
-
56
- Global.controllers.each do |controller|
57
- if map = controller.mapping
58
- Inform.debug("mapping #{map} => #{controller}")
59
- Global.mapping[map] ||= controller
60
- end
61
- end
60
+ tr, pr = Global.template_root, Global.public_root
61
+ Inform.warn("Template root: #{tr} doesn't exist") unless File.directory?(tr)
62
+ Inform.warn("Public root: #{pr} doesn't exist") unless File.directory?(pr)
62
63
 
63
64
  if Global.mapping.empty?
64
65
  Inform.warn("No Controllers mapped, will serve /public only.")
@@ -87,8 +88,12 @@ module Ramaze
87
88
  end
88
89
 
89
90
  # Map Controller to the given syms or strings.
91
+ # Replaces old mappings.
92
+ # If you want to _add_ a mapping, just modify Global.mapping.
90
93
 
91
94
  def map(*syms)
95
+ Global.mapping.delete_if{|k,v| v == self}
96
+
92
97
  syms.each do |sym|
93
98
  Global.mapping[sym.to_s] = self
94
99
  end
@@ -100,6 +105,37 @@ module Ramaze
100
105
  Global.mapping[mapping.to_s]
101
106
  end
102
107
 
108
+ # Define a layout for all actions on this controller
109
+ #
110
+ # Example:
111
+ # class Foo < Ramaze::Controller
112
+ # layout :foo
113
+ # end
114
+ #
115
+ # This defines the action :foo to be layout of the controller and will
116
+ # render the layout after any other action has been rendered, assigns
117
+ # @content to the result of the action and then goes on rendering
118
+ # the layout-action where @content may or may not be used, returning
119
+ # whatever the layout returns.
120
+
121
+ def layout(meth_or_hash, &block)
122
+ if meth_or_hash.respond_to?(:to_hash)
123
+ meth_or_hash.each do |layout_name, *actions|
124
+ actions.flatten.each do |action|
125
+ trait[:layout][action.to_s] = R(self, layout_name)
126
+ end
127
+ end
128
+ else
129
+ trait[:layout][:all] = R(self, meth_or_hash)
130
+ end
131
+ end
132
+
133
+ def deny_layout(*actions)
134
+ actions.each do |action|
135
+ trait[:layout][:deny] << action.to_s
136
+ end
137
+ end
138
+
103
139
  # Define a template_root for Controller, returns the current template_root
104
140
  # if no argument is given.
105
141
  # Runs every given path through Controller::check_path
@@ -148,6 +184,7 @@ module Ramaze
148
184
 
149
185
  def handle path
150
186
  action = resolve(path)
187
+ Thread.current[:controller] = action.controller
151
188
  action.render
152
189
  end
153
190
  end
@@ -3,6 +3,10 @@
3
3
 
4
4
  module Ramaze
5
5
  module Dispatcher
6
+
7
+ # This dispatcher is responsible for relaying requests to Controller::handle
8
+ # and filtering the results using FILTER.
9
+
6
10
  class Action
7
11
 
8
12
  # The response is passed to each filter by sending .call(response) to it.
@@ -20,7 +24,7 @@ module Ramaze
20
24
 
21
25
  def process(path)
22
26
  body = Controller.handle(path)
23
- response = Dispatcher.build_response(body)
27
+ response = Response.current.build(body)
24
28
  FILTER.inject(response){|r,f| f.call(r) }
25
29
  rescue Ramaze::Error => ex
26
30
  ex
@@ -0,0 +1,115 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Ramaze
5
+ module Dispatcher
6
+
7
+ # Generates a directory listing, see Ramaze::Controller::Directory for more
8
+ # information and how to create your own directory listing page
9
+ class Directory
10
+ class << self
11
+
12
+ # Entry point from Dispatcher::filter.
13
+ # Just a forwarder to build_listing, automatticly exiting if there is
14
+ # an error (defined by returning false in build_listing)
15
+ def process(path)
16
+ if Global.list_directories
17
+ response = build_listing(path)
18
+ Response.current.build(*response) if response
19
+ end
20
+ end
21
+
22
+ # Makes a request for http://yourserver/dirlist/path and returns the
23
+ # result. Due to this method, you can overwrite the action and create your
24
+ # own page. See Ramaze::Controller::Directory for more.
25
+ def build_listing(path)
26
+ dir = ::File.expand_path(Global.public_root/::File.expand_path(path, '/'))
27
+
28
+ if ::File.directory?(dir)
29
+ Inform.debug("Serving directory listing: #{dir}")
30
+
31
+ status = Ramaze::STATUS_CODE['OK']
32
+ header = {'Content-Type' => "text/html"}
33
+ body = list_for(dir)
34
+ [body, status, header]
35
+ end
36
+ end
37
+
38
+ def list_for(path)
39
+ display = path.gsub(/^#{Regexp.escape(Global.public_root)}\/?/, '/')
40
+ wrapper =
41
+ %(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
42
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
43
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
44
+ <head>
45
+ <title>Directory listing of #{display}</title>
46
+
47
+ <style type="text/css"> /*<![CDATA[*/ a, a:active {text-decoration: none; color: blue;} a:visited {color: #48468F;} a:hover, a:focus {text-decoration: underline; color: red;} body {background-color: #F5F5F5;} h2 {margin-bottom: 12px;} table {margin-left: 12px;} th, td { font-family: "Courier New", Courier, monospace; font-size: 10pt; text-align: left;} th { font-weight: bold; padding-right: 14px; padding-bottom: 3px;} td {padding-right: 14px;} td.s, th.s {text-align: right;} div.list { background-color: white; border-top: 1px solid #646464; border-bottom: 1px solid #646464; padding-top: 10px; padding-bottom: 14px;} div.foot { font-family: "Courier New", Courier, monospace; font-size: 10pt; color: #787878; padding-top: 4px;} /*]]>*/ </style>
48
+ </head>
49
+ <body>
50
+ <h2>Directory listing of #{display}</h2>
51
+ <div class="list">
52
+ <table summary="Directory Listing" cellpadding="0" cellspacing="0">
53
+ <thead>
54
+ <tr>
55
+ <th class="n">Name</th>
56
+ <th class="m">Last Modified</th>
57
+ <th class="s">Size</th>
58
+ <th class="t">Type</th>
59
+ </tr>
60
+ </thead>
61
+ <tbody>
62
+ <tr>
63
+ <td class="n"><a href="#{display/'..'}/">Parent Directory</a>/</td>
64
+ <td class="m">&nbsp;</td>
65
+ <td class="s">- &nbsp;</td>
66
+ <td class="t">Directory</td>
67
+ </tr>
68
+ %s
69
+ %s
70
+ </tbody>
71
+ </table>
72
+ </div>
73
+ <div class="foot">%s</div>
74
+ </body>
75
+ </html>
76
+ )
77
+
78
+ dirs, files = Dir[path/'*'].partition{|file| ::File.directory?(file) }
79
+ dir_body, file_body = [], []
80
+
81
+ dirs.each do |dir|
82
+ basename = ::File.basename(dir)
83
+ dir_body << %[<tr>
84
+ <td class="n"><a href="#{display/basename}">#{basename}/</a></td>
85
+ <td class="m">&nbsp;</td>
86
+ <td class="s">- &nbsp;</td>
87
+ <td class="t">Directory</td>
88
+ </tr>]
89
+ end
90
+
91
+ time_format = "%Y-%b-%d %H:%M:%S"
92
+ files.each do |file|
93
+ basename = ::File.basename(file)
94
+ time = ::File.mtime(file).strftime(time_format)
95
+ size = ::File.size(file).human_readable_filesize_format
96
+ mime = Tool::MIME.type_for(file)
97
+ file_body << %[<tr>
98
+ <td class="n"><a href="#{display/basename}">#{basename}</a></td>
99
+ <td class="m">#{time}</td>
100
+ <td class="s">#{size}</td>
101
+ <td class="t">#{mime}</td>
102
+ </tr>]
103
+ end
104
+
105
+ version = "ramaze/#{Ramaze::VERSION}"
106
+ wrapper % [
107
+ dir_body. join("\n "),
108
+ file_body.join("\n "),
109
+ version
110
+ ]
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end