ramaze 0.0.9 → 0.1.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 (193) hide show
  1. data/Rakefile +14 -259
  2. data/bin/ramaze +52 -25
  3. data/doc/AUTHORS +6 -0
  4. data/doc/CHANGELOG +1363 -42
  5. data/doc/INSTALL +1 -1
  6. data/doc/README +48 -35
  7. data/doc/README.html +637 -0
  8. data/doc/TODO +7 -16
  9. data/doc/allison/allison.css +6 -7
  10. data/doc/allison/allison.gif +0 -0
  11. data/doc/allison/cache/STYLE +1 -2
  12. data/doc/changes.txt +3375 -0
  13. data/doc/changes.xml +3378 -0
  14. data/doc/meta/announcement.txt +47 -0
  15. data/doc/meta/configuration.txt +179 -0
  16. data/doc/meta/internals.txt +111 -0
  17. data/doc/readme_chunks/features.txt +8 -16
  18. data/doc/readme_chunks/installing.txt +7 -1
  19. data/doc/tutorial/todolist.txt +2 -3
  20. data/examples/blog/main.rb +9 -8
  21. data/examples/blog/public/styles/blog.css +132 -0
  22. data/examples/blog/src/controller.rb +14 -41
  23. data/examples/blog/src/model.rb +12 -13
  24. data/examples/blog/src/view.rb +16 -0
  25. data/examples/blog/template/edit.xhtml +19 -8
  26. data/examples/blog/template/index.xhtml +14 -22
  27. data/examples/blog/template/new.xhtml +18 -5
  28. data/examples/caching.rb +5 -8
  29. data/examples/element.rb +3 -3
  30. data/examples/hello.rb +3 -5
  31. data/examples/simple.rb +4 -7
  32. data/examples/templates/template/external.haml +8 -7
  33. data/examples/templates/template/external.mab +11 -8
  34. data/examples/templates/template_amrita2.rb +4 -4
  35. data/examples/templates/template_erubis.rb +3 -3
  36. data/examples/templates/template_ezamar.rb +1 -2
  37. data/examples/templates/template_haml.rb +24 -23
  38. data/examples/templates/template_liquid.rb +3 -1
  39. data/examples/templates/template_markaby.rb +15 -9
  40. data/examples/todolist/src/element/page.rb +1 -1
  41. data/lib/proto/conf/benchmark.yaml +6 -20
  42. data/lib/proto/conf/debug.yaml +6 -19
  43. data/lib/proto/conf/live.yaml +7 -19
  44. data/lib/proto/conf/silent.yaml +6 -16
  45. data/lib/proto/conf/stage.yaml +6 -18
  46. data/lib/proto/public/error.zmr +2 -2
  47. data/lib/ramaze.rb +34 -72
  48. data/lib/ramaze/adapter.rb +21 -18
  49. data/lib/ramaze/adapter/mongrel.rb +0 -3
  50. data/lib/ramaze/adapter/webrick.rb +6 -6
  51. data/lib/ramaze/cache/memcached.rb +3 -0
  52. data/lib/ramaze/controller.rb +227 -183
  53. data/lib/ramaze/dispatcher.rb +34 -129
  54. data/lib/ramaze/dispatcher/action.rb +28 -0
  55. data/lib/ramaze/dispatcher/error.rb +43 -0
  56. data/lib/ramaze/dispatcher/file.rb +34 -0
  57. data/lib/ramaze/global.rb +89 -48
  58. data/lib/ramaze/helper/aspect.rb +8 -6
  59. data/lib/ramaze/helper/auth.rb +3 -3
  60. data/lib/ramaze/helper/cache.rb +2 -2
  61. data/lib/ramaze/helper/file.rb +14 -0
  62. data/lib/ramaze/helper/inform.rb +36 -0
  63. data/lib/ramaze/helper/link.rb +7 -3
  64. data/lib/ramaze/helper/markaby.rb +30 -0
  65. data/lib/ramaze/helper/redirect.rb +2 -0
  66. data/lib/ramaze/inform.rb +8 -182
  67. data/lib/ramaze/inform/analogger.rb +19 -0
  68. data/lib/ramaze/inform/growl.rb +28 -0
  69. data/lib/ramaze/inform/hub.rb +26 -0
  70. data/lib/ramaze/inform/informer.rb +92 -0
  71. data/lib/ramaze/inform/informing.rb +44 -0
  72. data/lib/ramaze/inform/syslog.rb +27 -0
  73. data/lib/ramaze/inform/xosd.rb +42 -0
  74. data/lib/ramaze/snippets.rb +6 -2
  75. data/lib/ramaze/snippets/object/traits.rb +13 -1
  76. data/lib/ramaze/snippets/ramaze/autoreload.rb +58 -2
  77. data/lib/ramaze/snippets/string/color.rb +27 -0
  78. data/lib/ramaze/snippets/string/each.rb +6 -0
  79. data/lib/ramaze/snippets/struct/fill.rb +15 -0
  80. data/lib/ramaze/template/ezamar.rb +13 -22
  81. data/lib/ramaze/template/ezamar/element.rb +12 -12
  82. data/lib/ramaze/template/liquid.rb +19 -18
  83. data/lib/ramaze/template/markaby.rb +37 -58
  84. data/lib/ramaze/tool/localize.rb +128 -0
  85. data/lib/ramaze/tool/tidy.rb +51 -21
  86. data/lib/ramaze/trinity.rb +3 -3
  87. data/lib/ramaze/trinity/request.rb +41 -23
  88. data/lib/ramaze/trinity/response.rb +10 -5
  89. data/lib/ramaze/trinity/session.rb +17 -3
  90. data/lib/ramaze/version.rb +2 -2
  91. data/rake_tasks/conf.rake +56 -0
  92. data/rake_tasks/gem.rake +44 -0
  93. data/rake_tasks/maintaince.rake +187 -0
  94. data/spec/all.rb +32 -0
  95. data/spec/examples/caching.rb +19 -0
  96. data/spec/examples/element.rb +15 -0
  97. data/spec/examples/hello.rb +11 -0
  98. data/spec/examples/simple.rb +51 -0
  99. data/spec/examples/templates/template_amrita2.rb +14 -0
  100. data/spec/examples/templates/template_erubis.rb +21 -0
  101. data/spec/examples/templates/template_ezamar.rb +22 -0
  102. data/spec/examples/templates/template_haml.rb +23 -0
  103. data/spec/examples/templates/template_liquid.rb +24 -0
  104. data/spec/examples/templates/template_markaby.rb +21 -0
  105. data/spec/helper.rb +81 -0
  106. data/spec/{spec_helper_context.rb → helper/context.rb} +1 -1
  107. data/spec/helper/layout.rb +55 -0
  108. data/spec/helper/mock_http.rb +66 -0
  109. data/spec/{spec_helper_requester.rb → helper/requester.rb} +0 -6
  110. data/spec/{spec_helper_simple_http.rb → helper/simple_http.rb} +57 -57
  111. data/spec/helper/wrap.rb +193 -0
  112. data/spec/{adapter_spec.rb → ramaze/adapter.rb} +7 -5
  113. data/spec/{tc_adapter_mongrel.rb → ramaze/adapter/mongrel.rb} +2 -2
  114. data/spec/{tc_adapter_webrick.rb → ramaze/adapter/webrick.rb} +2 -2
  115. data/spec/{tc_cache.rb → ramaze/cache.rb} +16 -16
  116. data/spec/ramaze/conf/locale_de.yaml +6 -0
  117. data/spec/ramaze/conf/locale_en.yaml +6 -0
  118. data/spec/ramaze/controller.rb +184 -0
  119. data/spec/ramaze/controller/template/greet.xhtml +1 -0
  120. data/spec/ramaze/controller/template_resolving.rb +54 -0
  121. data/spec/ramaze/dependencies.rb +16 -0
  122. data/spec/{tc_element.rb → ramaze/element.rb} +21 -19
  123. data/spec/ramaze/error.rb +64 -0
  124. data/spec/{tc_gestalt.rb → ramaze/gestalt.rb} +10 -10
  125. data/spec/{tc_global.rb → ramaze/global.rb} +7 -7
  126. data/spec/{tc_helper_aspect.rb → ramaze/helper/aspect.rb} +22 -14
  127. data/spec/{tc_helper_auth.rb → ramaze/helper/auth.rb} +9 -7
  128. data/spec/{tc_helper_cache.rb → ramaze/helper/cache.rb} +14 -24
  129. data/spec/{tc_helper_feed.rb → ramaze/helper/feed.rb} +12 -12
  130. data/spec/ramaze/helper/file.rb +17 -0
  131. data/spec/{tc_helper_flash.rb → ramaze/helper/flash.rb} +16 -17
  132. data/spec/{tc_helper_form.rb → ramaze/helper/form.rb} +25 -26
  133. data/spec/{tc_helper_link.rb → ramaze/helper/link.rb} +9 -9
  134. data/spec/{tc_helper_redirect.rb → ramaze/helper/redirect.rb} +11 -10
  135. data/spec/{tc_helper_stack.rb → ramaze/helper/stack.rb} +10 -11
  136. data/spec/ramaze/inform/informer.rb +40 -0
  137. data/spec/ramaze/inform/syslog.rb +10 -0
  138. data/spec/ramaze/localize.rb +40 -0
  139. data/spec/ramaze/morpher.rb +82 -0
  140. data/spec/ramaze/params.rb +124 -0
  141. data/spec/{public → ramaze/public}/error404.xhtml +0 -0
  142. data/spec/{public → ramaze/public}/favicon.ico +0 -0
  143. data/spec/{public → ramaze/public}/ramaze.png +0 -0
  144. data/spec/{public → ramaze/public}/test_download.css +0 -0
  145. data/spec/ramaze/request.rb +129 -0
  146. data/spec/{tc_request_mongrel.rb → ramaze/request/mongrel.rb} +2 -2
  147. data/spec/{tc_request_webrick.rb → ramaze/request/webrick.rb} +1 -1
  148. data/spec/{tc_session.rb → ramaze/session.rb} +18 -18
  149. data/spec/{tc_store.rb → ramaze/store/default.rb} +10 -10
  150. data/spec/{tc_store_yaml.rb → ramaze/store/yaml.rb} +9 -9
  151. data/spec/ramaze/template.rb +86 -0
  152. data/spec/{tc_template_amrita2.rb → ramaze/template/amrita2.rb} +5 -5
  153. data/spec/{template → ramaze/template}/amrita2/data.amrita +0 -0
  154. data/spec/{template → ramaze/template}/amrita2/index.amrita +0 -0
  155. data/spec/{template → ramaze/template}/amrita2/sum.amrita +0 -0
  156. data/spec/{tc_template_erubis.rb → ramaze/template/erubis.rb} +9 -9
  157. data/spec/{template → ramaze/template}/erubis/sum.rhtml +0 -0
  158. data/spec/ramaze/template/ezamar.rb +62 -0
  159. data/spec/{template → ramaze/template}/ezamar/another/long/action.zmr +0 -0
  160. data/spec/{template → ramaze/template}/ezamar/combined.zmr +0 -0
  161. data/spec/{template → ramaze/template}/ezamar/file_only.zmr +0 -0
  162. data/spec/{template → ramaze/template}/ezamar/index.zmr +0 -0
  163. data/spec/ramaze/template/ezamar/nested.zmr +1 -0
  164. data/spec/{template → ramaze/template}/ezamar/some__long__action.zmr +0 -0
  165. data/spec/{template → ramaze/template}/ezamar/sum.zmr +0 -0
  166. data/spec/{tc_template_haml.rb → ramaze/template/haml.rb} +7 -7
  167. data/spec/{template → ramaze/template}/haml/index.haml +0 -0
  168. data/spec/{template → ramaze/template}/haml/with_vars.haml +0 -0
  169. data/spec/{tc_template_liquid.rb → ramaze/template/liquid.rb} +7 -7
  170. data/spec/{template → ramaze/template}/liquid/index.liquid +0 -0
  171. data/spec/{template → ramaze/template}/liquid/products.liquid +0 -0
  172. data/spec/ramaze/template/markaby.rb +59 -0
  173. data/spec/{template → ramaze/template}/markaby/external.mab +0 -0
  174. data/spec/{template → ramaze/template}/markaby/sum.mab +0 -0
  175. data/spec/ramaze/template/ramaze/external.test +1 -0
  176. data/spec/{tc_tidy.rb → ramaze/tidy.rb} +3 -3
  177. metadata +145 -81
  178. data/examples/blog/public/screen.css +0 -106
  179. data/examples/blog/src/element.rb +0 -58
  180. data/examples/blog/template/view.xhtml +0 -15
  181. data/examples/blog/test/tc_entry.rb +0 -18
  182. data/lib/proto/public/404.jpg +0 -0
  183. data/spec/request_tc_helper.rb +0 -135
  184. data/spec/spec_all.rb +0 -118
  185. data/spec/spec_helper.rb +0 -66
  186. data/spec/tc_controller.rb +0 -49
  187. data/spec/tc_dependencies.rb +0 -13
  188. data/spec/tc_error.rb +0 -43
  189. data/spec/tc_morpher.rb +0 -88
  190. data/spec/tc_params.rb +0 -125
  191. data/spec/tc_template_ezamar.rb +0 -64
  192. data/spec/tc_template_markaby.rb +0 -72
  193. data/spec/template/ezamar/nested.zmr +0 -1
@@ -4,14 +4,24 @@
4
4
  require 'rack'
5
5
  require 'benchmark'
6
6
 
7
+ require 'ramaze/trinity'
8
+
7
9
  # for OSX compatibility
8
10
  Socket.do_not_reverse_lookup = true
9
11
 
12
+ class Rack::Request
13
+ include Ramaze::Request
14
+ end
15
+
16
+ class Rack::Response
17
+ include Ramaze::Response
18
+ end
19
+
10
20
  module Ramaze::Adapter
11
21
  class Base
12
22
  class << self
13
23
  def stop
14
- Informer.debug "Stopping #{self.class}"
24
+ Inform.debug("Stopping #{self.class}")
15
25
  end
16
26
 
17
27
  def call(env)
@@ -20,32 +30,25 @@ module Ramaze::Adapter
20
30
  end
21
31
 
22
32
  def call(env)
23
- if Ramaze::Global.inform_tags.include?(:benchmark)
33
+ if Ramaze::Global.benchmarking
24
34
  time = Benchmark.measure{ respond env }
25
- info "request took #{time.real}s"
35
+ Inform.debug("request took #{time.real}s")
26
36
  else
27
37
  respond env
28
38
  end
29
39
 
30
- @response = Thread.current[:response]
31
-
32
- [@response.status, @response.header, self]
40
+ finish
33
41
  end
34
42
 
35
- def respond env
36
- Ramaze::Dispatcher.handle(::Rack::Request.new(env), ::Rack::Response.new)
37
- end
43
+ def finish
44
+ response = Thread.current[:response]
38
45
 
39
- def each
40
- body = @response.body
46
+ response.finish
47
+ end
41
48
 
42
- if body.respond_to?(:read)
43
- until body.eof?
44
- yield body.read(1024)
45
- end
46
- else
47
- yield body
48
- end
49
+ def respond env
50
+ request, response = Rack::Request.new(env), Rack::Response.new
51
+ Ramaze::Dispatcher.handle(request, response)
49
52
  end
50
53
  end
51
54
  end
@@ -5,9 +5,6 @@ require 'ramaze/adapter'
5
5
 
6
6
  require 'mongrel'
7
7
 
8
- # for OSX compatibility
9
- Socket.do_not_reverse_lookup = true
10
-
11
8
  module Ramaze::Adapter
12
9
  class Mongrel < Base
13
10
  class << self
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'ramaze/adapter'
5
5
 
6
- require 'webrick'
6
+ require 'rack/handler/webrick'
7
7
 
8
8
  module WEBrick
9
9
  module HTTPServlet
@@ -25,16 +25,16 @@ module Ramaze::Adapter
25
25
  options = {
26
26
  :Port => port,
27
27
  :BindAddress => host,
28
- :Logger => Ramaze::Informer,
28
+ :Logger => Ramaze::Inform,
29
29
  :AccessLog => [
30
- [Ramaze::Informer, WEBrick::AccessLog::COMMON_LOG_FORMAT],
31
- [Ramaze::Informer, WEBrick::AccessLog::REFERER_LOG_FORMAT]
30
+ [Ramaze::Inform, WEBrick::AccessLog::COMMON_LOG_FORMAT],
31
+ [Ramaze::Inform, WEBrick::AccessLog::REFERER_LOG_FORMAT]
32
32
  ]
33
33
  }.merge(options)
34
34
 
35
35
  Thread.new do
36
- Thread.current[:task] = :webrick
37
- Rack::Handler::WEBrick.run(self, options)
36
+ Thread.current[:adapter] =
37
+ Rack::Handler::WEBrick.run(self, options)
38
38
  end
39
39
  end
40
40
  end
@@ -33,6 +33,9 @@ module Ramaze
33
33
 
34
34
  def method_missing(*args, &block)
35
35
  @cache.__send__(*args, &block)
36
+ rescue MemCache::MemCacheError => e
37
+ Ramaze::Inform.error e.to_s
38
+ nil
36
39
  end
37
40
 
38
41
  # out of some reason MemCache sometimes doesn't respond to
@@ -5,249 +5,292 @@ require 'ramaze/template'
5
5
 
6
6
  module Ramaze
7
7
 
8
+ class Action < Struct.new('Action', :method, :params, :template)
9
+ def to_s
10
+ %{#<Action method=#{method.inspect}, params=#{params.inspect} template=#{template.inspect}>}
11
+ end
12
+ end
13
+
8
14
  # The Controller is responsible for combining and rendering actions.
9
15
 
10
16
  class Controller
11
17
  include Ramaze::Helper
12
18
  extend Ramaze::Helper
13
19
 
14
- helper :redirect, :link
20
+ helper :redirect, :link, :file
15
21
 
16
22
  trait :template_extensions => { }
17
23
 
18
24
  # Path to the ramaze-internal public directory for error-pages and the like.
19
25
  # It acts just as a shadow.
20
- trait :public => ( ::Ramaze::BASEDIR / 'proto' / 'public' )
26
+ trait :ramaze_public => ( ::Ramaze::BASEDIR / 'proto' / 'public' )
27
+
28
+ # Whether or not to map this controller on startup automatically
29
+
30
+ trait :automap => true
31
+
32
+ # Place to map the Controller to, this is something like '/' or '/foo'
33
+
34
+ trait :map => nil
35
+
36
+ trait :exclude_action_modules => [Kernel, Object, PP::ObjectMixin]
37
+
38
+ trait :pattern_cache => Hash.new{|h,k| h[k] = Controller.pattern_for(k) }
39
+
40
+ trait :action_cache => Global.cache.new
21
41
 
22
42
  class << self
23
43
  include Ramaze::Helper
24
44
  extend Ramaze::Helper
25
45
 
46
+ def inherited controller
47
+ controller.trait :actions_cached => Set.new
48
+ Global.controllers << controller
49
+ end
50
+
51
+ def validate_sanity
52
+ if path = trait[:public]
53
+ unless File.directory?(path)
54
+ Inform.warn("#{controller} uses templating in #{path}, which does not exist")
55
+ end
56
+ end
57
+ end
58
+
59
+ def mapping
60
+ global_mapping = Global.mapping.invert[self]
61
+ return global_mapping if global_mapping
62
+ if map = class_trait[:map]
63
+ map
64
+ elsif ancestral_trait[:automap]
65
+ name = self.to_s.gsub('Controller', '').split('::').last
66
+ %w[Main Base Index].include?(name) ? '/' : "/#{name.snake_case}"
67
+ end
68
+ end
69
+
70
+ def map(*syms)
71
+ syms.each do |sym|
72
+ Global.mapping[sym.to_s] = self
73
+ end
74
+ end
75
+
76
+ def current
77
+ Thread.current[:controller]
78
+ end
79
+
26
80
  def handle path
27
- controller, action, params = *resolve_controller(path)
28
- action, params = path.gsub(/^\//, '').split('/').join('__'), [] unless action
29
- controller = self unless controller
30
- controller.render action, *params
31
- rescue Ramaze::Error::Template => ex
32
- puts ex
33
- ''
81
+ controller, action = *resolve(path)
82
+ controller.render(action)
34
83
  end
35
84
 
36
- # find out which controller should be used based on the path.
37
- # it will answer [controller, action, params] or raise an
38
- #
39
- # Ramaze::Error::NoController # if no controller is found
40
- # Ramaze::Error::NoAction # if no action but a controller is found
41
- #
42
- # It actually uses #resolve_action on almost every combination of
43
- # so-called paractions (yet unsplit but possible combination of action
44
- # and parameters for the action)
45
- #
46
- # If your templating is action-less, which means it does not depend on
47
- # methods on the controller, but rather on templates or just dynamically
48
- # calculated stuff you can set trait[:actionless] for your templating.
49
- #
50
- # Please see the documentation for Ramaze::Template::Amrita2 for an more
51
- # specific example of how it is used in practice.
52
- #
53
- # Further it uses the Global.mapping to look up the controller to be used.
54
- #
55
- # Also, the action '/' will be expanded to 'index'
85
+
86
+ # #ramaze - 9.5.2007
56
87
  #
57
- # Parameters are CGI.unescaped
88
+ # manveru | if no possible controller is found, it's a NoController error
89
+ # manveru | that would be a 404 then
90
+ # Kashia | aye
91
+ # manveru | if some controller are found but no actions on them, it's NoAction Error for the first controller found, again, 404
92
+ # manveru | everything further down is considered 500
58
93
 
59
- def resolve_controller path
60
- Informer.meth_debug :resolve_controller, path
61
- track = path.split('/')
62
- controller = false
63
- action = false
64
- tracks = []
94
+ def resolve(path)
95
+ #Inform.debug("resolve_controller('#{path}')")
96
+ mapping = Global.mapping
97
+ controllers = Global.controllers
65
98
 
66
- track.unshift '/'
99
+ raise_no_controller(path) if controllers.empty? or mapping.empty?
67
100
 
68
- track.each do |atom|
69
- tracks << (tracks.last.to_s / atom)
70
- end
101
+ patterns = Controller.trait[:pattern_cache][path]
102
+ first_controller = nil
71
103
 
72
- until controller and action or tracks.empty?
73
- current = Regexp.escape(tracks.pop.to_s)
74
- paraction = path.gsub(/^#{current}/, '').split('/').map{|e| CGI.unescape(e)}
75
- paraction.delete('')
76
- if controller = Ramaze::Global.mapping[current] and controller.respond_to?(:render)
77
- if paraction == ['error']
78
-
79
- action = paraction.shift
80
- params = paraction
81
- action = 'index' if action == nil
82
- else
83
- action, params = resolve_action controller, paraction
84
- end
104
+ patterns.each do |controller, method, params|
105
+ if controller = mapping[controller]
106
+ first_controller ||= controller
107
+
108
+ action = controller.resolve_action(method, *params)
109
+ template = action.template
110
+
111
+ action.method ||= File.basename(template, File.extname(template)) if template
112
+
113
+ return controller, action if action.method
85
114
  end
86
115
  end
87
116
 
88
- return controller, action, params
117
+ raise_no_action(first_controller, path) if first_controller
118
+ raise_no_controller(path)
89
119
  end
90
120
 
91
- # Resolve the method to be called and the number of parameters
92
- # it will receive for a specific class (the controller) given the
93
- # paraction (like 'foo/bar' => controller.call('foo', 'bar'))
94
- # in case arity is 1 and a public instance-method named foo is defined.
95
- #
96
- # TODO:
97
- # - find a solution for def x(a = :a) which has arity -1
98
- # identical to def x(*a) for some odd reason
121
+ def resolve_action(path, *parameter)
122
+ path, parameter = path.to_s, parameter.map(&:to_s)
123
+ possible_path = trait["#{path}_template".to_sym]
124
+ template = resolve(possible_path).last.template if possible_path
99
125
 
100
- def resolve_action controller, paraction
101
- Informer.meth_debug :resolve_action, controller, paraction
126
+ method, params = resolve_method(path, *parameter)
102
127
 
103
- meths =
104
- (controller.ancestors - [Kernel, Object]).inject([]) do |sum, klass|
105
- sum | (klass.is_a?(Module) ? klass.instance_methods(false) : sum)
106
- end
128
+ if method or parameter.empty?
129
+ template ||= resolve_template(path)
130
+ end
131
+
132
+ Action.new(method, params, template)
133
+ end
134
+
135
+ def resolve_template(action)
136
+ action = action.to_s
137
+ action_converted = action.split('__').inject{|s,v| s/v}
138
+ actions = [action, action_converted].compact
107
139
 
108
- track = paraction.dup
109
- tracks = []
110
- action = false
140
+ paths = template_paths.map{|pa| actions.map{|a| pa/a } }.flatten.uniq
141
+ glob = "{#{paths.join(',')}}.{#{extension_order.join(',')}}"
142
+
143
+ Dir[glob].first
144
+ end
145
+
146
+ def template_paths
147
+ klass_public = trait[:public]
148
+ ramaze_public = Controller.trait[:ramaze_public]
149
+
150
+ first_path =
151
+ if template_root = class_trait[:template_root]
152
+ template_root
153
+ else
154
+ Global.template_root / Global.mapping.invert[self]
155
+ end
156
+ [ first_path, klass_public, ramaze_public].compact
157
+ end
111
158
 
112
- track.each do |atom|
113
- atom = [tracks.last.to_s, atom]
114
- atom.delete('')
115
- tracks << atom.join('__')
159
+ def resolve_method(name, *params)
160
+ if method = action_methods.delete(name)
161
+ arity = instance_method(method).arity
162
+ if params.size == arity or arity < 0
163
+ return method, params
164
+ end
116
165
  end
166
+ return nil, []
167
+ end
168
+
169
+ def action_methods
170
+ exclude = Controller.trait[:exclude_action_modules]
171
+
172
+ ancs = (ancestors - exclude).select{|a| a.is_a?(Module)}
173
+ ancs.map{|a| a.instance_methods(false).map(&:to_s)}.flatten.uniq
174
+ end
175
+
176
+ def pattern_for(path)
177
+ atoms = path.split('/').grep(/\S/)
178
+ atoms.unshift('')
179
+ patterns, joiners = [], ['/']
180
+
181
+ atoms.size.times do |enum|
182
+ enum += 1
183
+ joiners << '__' if enum == 3
117
184
 
118
- tracks.unshift 'index'
185
+ joiners.each do |joinus|
186
+ pattern = atoms.dup
119
187
 
120
- until action or tracks.empty?
121
- current = tracks.pop
122
- if meths.include?(current) #or current = controller.ancestral_trait[:template_map][current]
123
- arity = controller.instance_method(current).arity
124
- params = (paraction - current.split('__'))
188
+ controller = pattern[0, enum].join(joinus)
189
+ controller.gsub!(/^__/, '/')
190
+ controller = "/" if controller == ""
125
191
 
126
- if params.size == arity
127
- return current, params
128
- elsif arity < 0
129
- return current, params
192
+ pattern = pattern[enum..-1]
193
+ args, temp = [], []
194
+
195
+ patterns << [controller, 'index', atoms[enum..-1]]
196
+
197
+ until pattern.empty?
198
+ args << pattern.shift
199
+ patterns << [controller, args.join( '__' ), pattern.dup]
130
200
  end
131
201
  end
132
202
  end
203
+
204
+ patterns.reverse!
133
205
  end
134
206
 
135
- # The universal #render method that has to be provided by every
136
- # prospective Controller, pass it your action and parameters.
137
- #
138
- # This is called upon by the Dispatcher, but you can use it in your
139
- # Controller/View to get the contents of another action.
140
- #
141
- # It will set the instance-variable @action in the instance of itself
142
- # to the value of the current action.
207
+ def extension_order
208
+ t_extensions = Controller.trait[:template_extensions]
209
+ engine = trait[:engine]
210
+ c_extensions = t_extensions.reject{|k,v| v != engine}.keys
211
+ all_extensions = t_extensions.keys
212
+ (c_extensions + all_extensions).uniq
213
+ end
143
214
 
144
- def render action, *parameter
145
- trait[:actions_cached] ||= Set.new
215
+ def render(action = {})
216
+ action = Action.fill(action) if action.is_a?(Hash)
217
+ Inform.debug("The Action: #{action}")
146
218
 
147
- cache_indicators = [
148
- Global.cache_all,
149
- ancestral_trait[:cache_all],
150
- ancestral_trait[:actions_cached].map{|k| k.to_s}.include?(action.to_s),
151
- ]
219
+ action.method = action.method.to_s
220
+ action.params.compact!
152
221
 
153
- if cache_indicators.any?
154
- cached_render(action, *parameter)
222
+ if cached?(action)
223
+ cached_render(action)
155
224
  else
156
- uncached_render(action, *parameter)
225
+ uncached_render(action)
157
226
  end
158
227
  end
159
228
 
160
- def uncached_render action, *parameter
161
- controller = self.new
162
- controller.instance_variable_set('@action', action)
229
+ def cached?(action)
230
+ actions_cached = trait[:actions_cached]
231
+
232
+ [ Global.cache_all,
233
+ trait[:cache_all],
234
+ actions_cached.map{|k| k.to_s}.include?(action.method),
235
+ ].any?
236
+ end
163
237
 
164
- file = find_template(action)
165
- engine = ancestral_trait[:engine] || engine_for(file)
238
+ def uncached_render(action)
239
+ controller = self.new
240
+ controller.instance_variable_set('@action', action.method)
241
+ Thread.current[:controller] = controller
166
242
 
167
243
  options = {
168
- :file => file,
169
- :binding => controller.send(:send, :binding),
170
- :action => action,
171
- :parameter => parameter,
244
+ :file => action.template,
245
+ :binding => controller.instance_eval{ binding },
246
+ :action => action.method,
247
+ :parameter => action.params,
172
248
  }
249
+
250
+ engine = select_engine(options[:file])
173
251
  engine.transform(controller, options)
174
252
  end
175
253
 
176
- def cached_render action, *parameter
177
- key = [action, parameter].inspect
178
-
179
- trait[:action_cache] ||= Global.cache.new
254
+ def cached_render action
255
+ action_cache = Controller.trait[:action_cache]
180
256
 
181
- if out = ancestral_trait[:action_cache][key]
182
- Informer.debug "Using Cached version for #{key}"
257
+ if out = action_cache[action]
258
+ Inform.debug("Using Cached version for #{action}")
183
259
  return out
184
260
  end
185
261
 
186
- Informer.debug "Compiling Action: #{action} #{parameter.join(', ')}"
187
- ancestral_trait[:action_cache][key] = uncached_render(action, *parameter)
262
+ Inform.debug("Compiling Action: #{action}")
263
+ action_cache[action] = uncached_render(action)
188
264
  end
189
265
 
190
- # This finds the template for the given action on the current controller
191
- # there are some basic ways how you can provide an alternative path:
192
- #
193
- # Global.template_root = 'default/path'
194
- #
195
- # class FooController < Controller
196
- # trait :template_root => 'another/path'
197
- # trait :index_template => :foo
198
- #
199
- # def index
200
- # end
201
- # end
202
- #
203
- # One feature also used in the above example is the custom template for
204
- # one action, in this case :index - now the template of :foo will be
205
- # used instead.
206
-
207
- def find_template action, klass = self
208
- custom_template = ancestral_trait["#{action}_template".intern]
209
- action = (custom_template ? custom_template : action).to_s
210
- action_converted = action.split('__').inject {|s,v| "#{s}/#{v}"}
211
-
212
- first_path =
213
- if template_root = klass.ancestral_trait[:template_root]
214
- template_root
215
- else
216
- Global.template_root / Global.mapping.invert[self]
217
- end
218
-
219
- extensions = [ancestral_trait[:template_extensions].values].flatten.uniq
266
+ def select_engine(file)
267
+ trait_engine = class_trait[:engine]
268
+ default = [trait_engine, Template::Ezamar].compact.first
269
+ return default unless file
220
270
 
221
- paths = [ first_path, ancestral_trait[:public], ].
222
- map{|pa| [ pa / action, pa / action_converted ] }.
223
- flatten.map{|pa| File.expand_path(pa) }.join(',')
271
+ engines = Controller.trait[:template_extensions]
272
+ return default if engines.empty?
224
273
 
225
- glob = "{#{paths}}.{#{extensions.join(',')}}"
226
-
227
- possible = Dir[glob]
228
- possible.first
229
- end
230
-
231
- # lookup the trait[:template_extensions] for the extname of the filename
232
- # you pass.
233
- #
234
- # Answers with the engine that matches the extension, Template::Ezamar
235
- # is used if none matches.
236
-
237
- def engine_for file
238
- file = file.to_s
239
- extension = File.extname(file).gsub(/^\./, '')
240
- engines = trait[:template_extensions]
241
- engines.find{|k,v| v == extension or [v].flatten.include?(extension)}.first
242
- rescue
243
- Template::Ezamar
274
+ ext = File.extname(file).gsub(/^\./, '')
275
+ ext_engine = engines[ext]
276
+ return ext_engine ? ext_engine : default
244
277
  end
245
278
 
246
279
  # This method is called by templating-engines to register themselves with
247
280
  # a list of extensions that will be looked up on #render of an action.
248
281
 
249
282
  def register_engine engine, *extensions
250
- trait[:template_extensions][engine] = [extensions].flatten.uniq
283
+ extensions.flatten.each do |ext|
284
+ trait[:template_extensions][ext] = engine
285
+ end
286
+ end
287
+
288
+ def raise_no_controller(path)
289
+ raise Ramaze::Error::NoController, "No Controller found for `#{path}'"
290
+ end
291
+
292
+ def raise_no_action(controller, path)
293
+ raise Ramaze::Error::NoAction, "No Action found for `#{path}' on #{controller}"
251
294
  end
252
295
  end
253
296
 
@@ -261,34 +304,35 @@ module Ramaze
261
304
 
262
305
  def error
263
306
  error = Thread.current[:exception]
264
- backtrace = error.backtrace[0..20]
307
+ @backtrace = error.backtrace[0..20]
265
308
  title = error.message
266
309
 
267
- colors = []
310
+ @colors = []
268
311
  min = 200
269
312
  max = 255
270
- step = -((max - min) / backtrace.size).abs
313
+ step = -((max - min) / @backtrace.size).abs
271
314
  max.step(min, step) do |color|
272
- colors << color
315
+ @colors << color
273
316
  end
274
317
 
275
- backtrace.map! do |line|
318
+ backtrace_size = Ramaze::Global.backtrace_size
319
+
320
+ @backtrace.map! do |line|
276
321
  file, lineno, meth = *Ramaze.parse_backtrace(line)
277
- backtrace_size = Ramaze::Global.inform_backtrace_size
278
322
  lines = Ramaze.caller_lines(file, lineno, backtrace_size)
279
323
 
280
324
  [ lines, lines.object_id.abs, file, lineno, meth ]
281
325
  end
282
326
 
283
- response.status = 404
284
-
285
- @backtrace = backtrace
286
- @colors = colors
287
327
  @title = CGI.escapeHTML(title)
288
328
  require 'coderay'
289
329
  @coderay = true
330
+ title
290
331
  rescue LoadError => ex
291
332
  @coderay = false
333
+ title
334
+ rescue Object => ex
335
+ Inform.error(ex)
292
336
  end
293
337
 
294
338
  private