ramaze 0.0.7 → 0.0.8

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 +52 -19
  2. data/bin/ramaze +19 -6
  3. data/doc/CHANGELOG +33 -0
  4. data/doc/COPYING +1 -1
  5. data/doc/FAQ +92 -0
  6. data/doc/GPL +340 -0
  7. data/doc/INSTALL +34 -0
  8. data/doc/ProjectInfo +53 -0
  9. data/doc/README +187 -110
  10. data/doc/readme_chunks/appendix.txt +13 -0
  11. data/doc/readme_chunks/examples.txt +38 -0
  12. data/doc/readme_chunks/features.txt +82 -0
  13. data/doc/readme_chunks/getting_help.txt +5 -0
  14. data/doc/readme_chunks/getting_started.txt +18 -0
  15. data/doc/readme_chunks/installing.txt +41 -0
  16. data/doc/readme_chunks/introduction.txt +18 -0
  17. data/doc/readme_chunks/principles.txt +41 -0
  18. data/doc/readme_chunks/thanks.txt +59 -0
  19. data/doc/tutorial/todolist.txt +546 -0
  20. data/examples/blog/main.rb +1 -1
  21. data/examples/blog/src/controller.rb +13 -11
  22. data/examples/blog/src/element.rb +11 -6
  23. data/examples/blog/src/model.rb +8 -23
  24. data/examples/blog/template/edit.xhtml +3 -1
  25. data/examples/blog/template/index.xhtml +4 -4
  26. data/examples/caching.rb +4 -4
  27. data/examples/element.rb +10 -7
  28. data/examples/hello.rb +3 -4
  29. data/examples/simple.rb +5 -3
  30. data/examples/templates/template/external.amrita +19 -0
  31. data/examples/templates/template/{external.rmze → external.zmr} +2 -2
  32. data/examples/templates/template_amrita2.rb +48 -0
  33. data/examples/templates/template_erubis.rb +5 -2
  34. data/examples/templates/{template_ramaze.rb → template_ezamar.rb} +13 -7
  35. data/examples/templates/template_haml.rb +4 -1
  36. data/examples/templates/template_liquid.rb +2 -1
  37. data/examples/templates/template_markaby.rb +2 -1
  38. data/examples/todolist/conf/benchmark.yaml +35 -0
  39. data/examples/todolist/conf/debug.yaml +34 -0
  40. data/examples/todolist/conf/live.yaml +33 -0
  41. data/examples/todolist/conf/silent.yaml +31 -0
  42. data/examples/todolist/conf/stage.yaml +33 -0
  43. data/examples/todolist/main.rb +18 -0
  44. data/examples/todolist/public/404.jpg +0 -0
  45. data/examples/todolist/public/css/coderay.css +105 -0
  46. data/examples/todolist/public/css/ramaze_error.css +42 -0
  47. data/{lib/proto → examples/todolist}/public/error.xhtml +0 -0
  48. data/examples/todolist/public/favicon.ico +0 -0
  49. data/examples/todolist/public/js/jquery.js +1923 -0
  50. data/examples/todolist/public/ramaze.png +0 -0
  51. data/examples/todolist/src/controller/main.rb +56 -0
  52. data/examples/todolist/src/element/page.rb +26 -0
  53. data/examples/todolist/src/model.rb +14 -0
  54. data/examples/todolist/template/index.xhtml +17 -0
  55. data/examples/todolist/template/new.xhtml +7 -0
  56. data/examples/todolist/todolist.db +9 -0
  57. data/examples/whywiki/main.rb +3 -8
  58. data/examples/whywiki/template/show.xhtml +4 -0
  59. data/lib/proto/public/error.zmr +77 -0
  60. data/lib/proto/src/controller/main.rb +2 -1
  61. data/lib/proto/src/element/page.rb +2 -1
  62. data/lib/proto/src/model.rb +3 -2
  63. data/lib/ramaze.rb +7 -9
  64. data/lib/ramaze/adapter.rb +51 -0
  65. data/lib/ramaze/adapter/cgi.rb +23 -0
  66. data/lib/ramaze/adapter/fcgi.rb +22 -0
  67. data/lib/ramaze/adapter/mongrel.rb +7 -86
  68. data/lib/ramaze/adapter/webrick.rb +14 -133
  69. data/lib/ramaze/cache/memcached.rb +6 -0
  70. data/lib/ramaze/cache/yaml_store.rb +3 -1
  71. data/lib/ramaze/controller.rb +292 -2
  72. data/lib/ramaze/dispatcher.rb +85 -213
  73. data/lib/ramaze/error.rb +10 -0
  74. data/lib/ramaze/global.rb +8 -0
  75. data/lib/ramaze/helper/aspect.rb +30 -7
  76. data/lib/ramaze/helper/auth.rb +16 -9
  77. data/lib/ramaze/helper/cache.rb +40 -35
  78. data/lib/ramaze/helper/feed.rb +1 -1
  79. data/lib/ramaze/helper/flash.rb +34 -0
  80. data/lib/ramaze/helper/link.rb +8 -2
  81. data/lib/ramaze/helper/openid.rb +63 -0
  82. data/lib/ramaze/helper/redirect.rb +12 -11
  83. data/lib/ramaze/helper/stack.rb +5 -7
  84. data/lib/ramaze/inform.rb +12 -1
  85. data/lib/ramaze/snippets/kernel/aquire.rb +1 -1
  86. data/lib/ramaze/snippets/kernel/{self_method.rb → method.rb} +3 -18
  87. data/lib/ramaze/snippets/kernel/{rescue_require.rb → pretty_inspect.rb} +7 -6
  88. data/lib/ramaze/snippets/method/name.rb +22 -0
  89. data/lib/ramaze/snippets/{kernel → ramaze}/autoreload.rb +0 -0
  90. data/lib/ramaze/snippets/ramaze/caller_info.rb +14 -0
  91. data/lib/ramaze/snippets/{kernel → ramaze}/caller_lines.rb +3 -10
  92. data/lib/ramaze/snippets/rdoc/usage_no_exit.rb +49 -23
  93. data/lib/ramaze/snippets/string/DIVIDE.rb +0 -1
  94. data/lib/ramaze/store/default.rb +58 -2
  95. data/lib/ramaze/store/yaml.rb +161 -0
  96. data/lib/ramaze/template.rb +27 -86
  97. data/lib/ramaze/template/amrita2.rb +14 -19
  98. data/lib/ramaze/template/erubis.rb +15 -38
  99. data/lib/ramaze/template/ezamar.rb +100 -0
  100. data/lib/ramaze/template/ezamar/element.rb +166 -0
  101. data/lib/ramaze/template/ezamar/engine.rb +124 -0
  102. data/lib/ramaze/template/ezamar/morpher.rb +155 -0
  103. data/lib/ramaze/template/haml.rb +16 -43
  104. data/lib/ramaze/template/liquid.rb +11 -51
  105. data/lib/ramaze/template/markaby.rb +44 -42
  106. data/lib/ramaze/tool/mime.rb +18 -0
  107. data/lib/ramaze/tool/mime_types.yaml +615 -0
  108. data/lib/ramaze/trinity/request.rb +20 -196
  109. data/lib/ramaze/trinity/response.rb +4 -33
  110. data/lib/ramaze/trinity/session.rb +150 -72
  111. data/lib/ramaze/version.rb +1 -1
  112. data/spec/adapter_spec.rb +20 -0
  113. data/spec/public/favicon.ico +0 -0
  114. data/spec/public/ramaze.png +0 -0
  115. data/spec/public/test_download.css +141 -0
  116. data/spec/{tc_request.rb → request_tc_helper.rb} +45 -21
  117. data/spec/spec_all.rb +77 -34
  118. data/spec/spec_helper.rb +8 -157
  119. data/spec/spec_helper_context.rb +72 -0
  120. data/spec/spec_helper_requester.rb +52 -0
  121. data/spec/spec_helper_simple_http.rb +433 -0
  122. data/spec/tc_adapter_mongrel.rb +3 -15
  123. data/spec/tc_adapter_webrick.rb +4 -14
  124. data/spec/tc_cache.rb +3 -5
  125. data/spec/tc_controller.rb +22 -12
  126. data/spec/tc_dependencies.rb +13 -0
  127. data/spec/tc_element.rb +8 -7
  128. data/spec/tc_error.rb +13 -7
  129. data/spec/tc_global.rb +16 -18
  130. data/spec/tc_helper_aspect.rb +2 -4
  131. data/spec/tc_helper_auth.rb +15 -14
  132. data/spec/tc_helper_cache.rb +5 -7
  133. data/spec/tc_helper_feed.rb +0 -2
  134. data/spec/tc_helper_flash.rb +103 -0
  135. data/spec/tc_helper_form.rb +4 -6
  136. data/spec/tc_helper_link.rb +1 -3
  137. data/spec/tc_helper_redirect.rb +23 -8
  138. data/spec/tc_helper_stack.rb +31 -15
  139. data/spec/tc_morpher.rb +1 -3
  140. data/spec/tc_params.rb +48 -7
  141. data/spec/tc_request_mongrel.rb +9 -0
  142. data/spec/tc_request_webrick.rb +5 -0
  143. data/spec/tc_session.rb +41 -25
  144. data/spec/tc_store.rb +55 -6
  145. data/spec/tc_store_yaml.rb +71 -0
  146. data/spec/tc_template_amrita2.rb +3 -3
  147. data/spec/tc_template_erubis.rb +2 -3
  148. data/spec/{tc_template_ramaze.rb → tc_template_ezamar.rb} +15 -5
  149. data/spec/tc_template_haml.rb +4 -3
  150. data/spec/tc_template_liquid.rb +3 -4
  151. data/spec/tc_template_markaby.rb +4 -6
  152. data/spec/tc_tidy.rb +1 -3
  153. data/spec/template/amrita2/{data.html → data.amrita} +0 -0
  154. data/spec/template/amrita2/{index.html → index.amrita} +0 -0
  155. data/spec/template/amrita2/{sum.html → sum.amrita} +0 -0
  156. data/spec/template/ezamar/another/long/action.zmr +1 -0
  157. data/spec/template/ezamar/combined.zmr +1 -0
  158. data/spec/template/{ramaze/file_only.rmze → ezamar/file_only.zmr} +0 -0
  159. data/spec/template/{ramaze/index.rmze → ezamar/index.zmr} +0 -0
  160. data/spec/template/{ramaze/nested.rmze → ezamar/nested.zmr} +0 -0
  161. data/spec/template/ezamar/some__long__action.zmr +1 -0
  162. data/spec/template/{ramaze/sum.rmze → ezamar/sum.zmr} +0 -0
  163. metadata +181 -123
  164. data/doc/allison/LICENSE +0 -184
  165. data/doc/allison/README +0 -37
  166. data/doc/allison/allison.css +0 -300
  167. data/doc/allison/allison.gif +0 -0
  168. data/doc/allison/allison.js +0 -307
  169. data/doc/allison/allison.rb +0 -287
  170. data/doc/allison/cache/BODY +0 -588
  171. data/doc/allison/cache/CLASS_INDEX +0 -4
  172. data/doc/allison/cache/CLASS_PAGE +0 -1
  173. data/doc/allison/cache/FILE_INDEX +0 -4
  174. data/doc/allison/cache/FILE_PAGE +0 -1
  175. data/doc/allison/cache/FONTS +0 -1
  176. data/doc/allison/cache/FR_INDEX_BODY +0 -1
  177. data/doc/allison/cache/IMGPATH +0 -1
  178. data/doc/allison/cache/INDEX +0 -1
  179. data/doc/allison/cache/JAVASCRIPT +0 -307
  180. data/doc/allison/cache/METHOD_INDEX +0 -4
  181. data/doc/allison/cache/METHOD_LIST +0 -1
  182. data/doc/allison/cache/SRC_PAGE +0 -1
  183. data/doc/allison/cache/STYLE +0 -322
  184. data/doc/allison/cache/URL +0 -1
  185. data/doc/changes.txt +0 -2021
  186. data/doc/changes.xml +0 -2024
  187. data/lib/ramaze/snippets/kernel/silently.rb +0 -13
  188. data/lib/ramaze/snippets/thread/deadQUESTIONMARK.rb +0 -11
  189. data/lib/ramaze/template/haml/actionview_stub.rb +0 -20
  190. data/lib/ramaze/template/ramaze.rb +0 -177
  191. data/lib/ramaze/template/ramaze/element.rb +0 -166
  192. data/lib/ramaze/template/ramaze/morpher.rb +0 -156
  193. data/spec/tc_test.rb +0 -17
@@ -1,102 +1,43 @@
1
1
  # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
2
  # All files in this distribution are subject to the terms of the Ruby license.
3
3
 
4
- require 'ramaze/helper'
4
+ # This module serves as a namespace for all templates, it will autoload
5
+ # Amrita2, Erubis, Ezamar, Haml, Liquid and Markaby if you refer to them.
5
6
 
6
- module Ramaze::Template
7
- %w[ Amrita2 Erubis Haml Liquid Markaby Ramaze ].each do |const|
8
- autoload(const, "ramaze/template/#{const.downcase}")
9
- end
10
-
11
- class Template
12
- extend ::Ramaze::Helper
13
-
14
- # Path to the ramaze-internal public directory for error-pages and the like.
15
- # It acts just as a shadow.
16
- trait :public => ( ::Ramaze::BASEDIR / 'proto' / 'public' )
17
-
18
- helper :link, :redirect
19
-
20
- # This finds the template for the given action on the current controller
21
- # there are some basic ways how you can provide an alternative path:
22
- #
23
- # Global.template_root = 'default/path'
24
- #
25
- # class FooController < Template::Ramaze
26
- # trait :template_root => 'another/path'
27
- # trait :index_template => :foo
28
- #
29
- # def index
30
- # end
31
- # end
32
- #
33
- # One feature also used in the above example is the custom template for
34
- # one action, in this case :index - now the template of :foo will be
35
- # used instead.
36
-
37
- def self.find_template action
38
- action = action.to_s
39
- custom_template = ancestral_trait["#{action}_template".intern]
40
- action = custom_template if custom_template
41
-
42
- first_path =
43
- if template_root = ancestral_trait[:template_root]
44
- template_root
45
- else
46
- Global.template_root / Global.mapping.invert[self]
47
- end
7
+ module Ramaze
8
+ module Template
48
9
 
49
- extensions = ancestral_trait[:template_extensions]
50
-
51
- paths = [ first_path, ancestral_trait[:public], ]
52
- paths = paths.map{|pa| File.expand_path(pa / action)}.join(',')
53
-
54
- possible = Dir["{#{paths}}.{#{extensions.join(',')}}"]
55
- possible.first
10
+ %w[ Amrita2 Erubis Haml Liquid Markaby ].each do |const|
11
+ autoload(const, "ramaze/template/#{const.downcase}")
56
12
  end
57
13
 
58
- private
14
+ # The superclass for all templates, doesn't do much more than including
15
+ # Ramaze::Helper and defining #reaction_or_file
59
16
 
60
- # just call self.class.find_template(action)
61
-
62
- def find_template action
63
- self.class.find_template(action)
64
- end
17
+ class Template
18
+ include Ramaze::Helper
65
19
 
66
- # the default error-page handler. you can overwrite this method
67
- # in your controller and create your own error-template for use.
68
- #
69
- # Error-pages can be in whatever the templating-engine of your controller
70
- # is set to.
71
- # Thread.current[:exception]
72
- # holds the exception thrown.
20
+ class << self
73
21
 
74
- def error
75
- error = Thread.current[:exception]
76
- backtrace = error.backtrace[0..20]
77
- title = error.message
22
+ # pass it the results of the method of the controller
23
+ # and a possible file, it will see if the file is an actual file
24
+ # and otherwise answer the contents of the response from the controller
25
+ # if it responds to :to_str.
26
+ #
27
+ # Answers nil if none of both is valid.
78
28
 
79
- colors = []
80
- min = 160
81
- max = 255
82
- step = -((max - min) / backtrace.size).abs
83
- max.step(min, step) do |color|
84
- colors << color
85
- end
29
+ def reaction_or_file reaction, file
30
+ if file
31
+ File.read(file)
32
+ elsif reaction.respond_to? :to_str
33
+ reaction
34
+ end
35
+ end
86
36
 
87
- backtrace.map! do |line|
88
- file, lineno, meth = line.scan(/(.*?):(\d+)(?::in `(.*?)')?/).first
89
- lines = __caller_lines__(file, lineno, Global.inform_backtrace_size)
90
- [ lines, lines.object_id.abs, file, lineno, meth ]
37
+ def transform controller, options = {}
38
+ options.values_at(:action, :parameter, :file, :binding)
39
+ end
91
40
  end
92
-
93
- @backtrace = backtrace
94
- @colors = colors
95
- @title = title
96
- require 'coderay'
97
- @coderay = true
98
- rescue LoadError => ex
99
- @coderay = false
100
41
  end
101
42
  end
102
43
  end
@@ -4,36 +4,31 @@
4
4
  require 'amrita2/template'
5
5
 
6
6
  module Ramaze::Template
7
- class Amrita2 < Template
8
7
 
9
- # No actions on the controller are serached or called.
10
- trait :actionless => true
8
+ # Is responsible for compiling a template using the Amrita2 templating engine.
11
9
 
12
- # usual extensions for templates
13
- trait :template_extensions => %w[html]
10
+ class Amrita2 < Template
14
11
 
15
- class << self
16
- include Ramaze::Helper
12
+ Ramaze::Controller.register_engine self, %w[ amrita ]
17
13
 
18
- # initializes the handling of a request on the controller.
19
- # Creates a new instances of itself and sends the action and params.
20
- # Also tries to render the template.
21
- # In Theory you can use this standalone, this has not been tested though.
14
+ class << self
22
15
 
23
- def handle_request action, *params
16
+ # Takes a controller and the options :action, :parameter, :file and :binding
17
+ # The file is rendered using Amrita2::TemplateFile.
18
+ # The Controller is used as the object for expansion.
19
+ #
20
+ # The parameters are set to @params in the controller before expansion.
24
21
 
25
- file = find_template(action)
22
+ def transform controller, options = {}
23
+ action, parameter, file, bound = *super
26
24
 
27
- raise Ramaze::Error::Template, "No Template found for #{request.request_path}" unless file
25
+ raise Ramaze::Error::Template, "No Template found for #{Request.current.request_path}" unless file
28
26
 
29
27
  template = ::Amrita2::TemplateFile.new(file)
30
28
  out = ''
31
- template.expand(out, self.new)
29
+ controller.instance_variable_set('@params', parameter)
30
+ template.expand(out, controller)
32
31
  out
33
-
34
- rescue Object => ex
35
- Informer.error ex
36
- raise Ramaze::Error::NoAction, "No Action found for #{request.request_path}"
37
32
  end
38
33
  end
39
34
  end
@@ -4,55 +4,32 @@
4
4
  require 'erubis'
5
5
 
6
6
  module Ramaze::Template
7
- class Erubis < Template
8
- extend Ramaze::Helper
9
7
 
10
- # Actions consist of both templates and methods on the controller.
11
- trait :actionless => false
8
+ # Is responsible for compiling a template using the Erubis templating engine.
9
+
10
+ class Erubis < Template
12
11
 
13
- # usual extensions for templates.
14
- trait :template_extensions => %w[rhtml rmze xhtml html]
12
+ Ramaze::Controller.register_engine self, %w[ rhtml ]
15
13
 
16
14
  class << self
17
- # initializes the handling of a request on the controller.
18
- # Creates a new instances of itself and sends the action and params.
19
- # Also tries to render the template.
20
- # In Theory you can use this standalone, this has not been tested though.
21
15
 
22
- def handle_request action, *params
23
- controller = self.new
24
- controller.instance_variable_set('@action', action)
25
- result = controller.send(action, *params) if controller.respond_to?(action)
16
+ # Takes a controller and the options :action, :parameter, :file and :binding
17
+ #
18
+ # Builds a template out of the method on the controller and the
19
+ # template-file.
26
20
 
27
- file = find_template(action)
21
+ def transform controller, options = {}
22
+ action, parameter, file, bound = *super
28
23
 
29
- template =
30
- if file
31
- File.read(file)
32
- elsif result.respond_to? :to_str
33
- result
34
- end
24
+ reaction = controller.send(action, *parameter)
25
+ template = reaction_or_file(reaction, file)
35
26
 
36
27
  return '' unless template
37
28
 
38
- bound = result.is_a?(Binding) ? result : controller.send(:send, :binding)
39
-
40
- controller.send(:transform, template, bound, file)
41
- rescue Object => ex
42
- puts ex
43
- Informer.error ex
44
- ''
29
+ eruby = ::Erubis::Eruby.new(template)
30
+ eruby.init_evaluator(:filename => file) if file
31
+ eruby.result(bound)
45
32
  end
46
33
  end
47
-
48
- private
49
-
50
- # Transform any String via Erubis, takes an optional binding and filename
51
-
52
- def transform string, bound = binding, file = nil
53
- eruby = ::Erubis::Eruby.new(string)
54
- eruby.init_evaluator(:filename => file) if file
55
- eruby.result(bound)
56
- end
57
34
  end
58
35
  end
@@ -0,0 +1,100 @@
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
+ require 'ramaze/template/ezamar/engine'
5
+
6
+ module Ramaze
7
+ module Template
8
+
9
+ # Is responsible for compiling a template using the Ezamar templating engine.
10
+
11
+ class Ezamar < Template
12
+
13
+ Ramaze::Controller.register_engine self, %w[ xhtml zmr ]
14
+
15
+ trait :transform_pipeline => [ ::Ezamar::Element, ::Ezamar::Morpher, self ]
16
+ trait :actionless => true
17
+
18
+ class << self
19
+
20
+ # Takes a controller and the options :action, :parameter, :file and :binding
21
+ #
22
+ # Uses Ezamar::Template to compile the template.
23
+
24
+ def transform controller, options = {}
25
+ if options.has_key?(:pipeline)
26
+ template = ::Ezamar::Template.new(controller, options)
27
+ template.transform(options[:binding])
28
+ else
29
+ action, parameter, file, bound = *super
30
+
31
+ real_transform controller, bound, file, action, *parameter
32
+ end
33
+ end
34
+
35
+ # The actual transformation is done here.
36
+ #
37
+ # Getting the various possible template-files and the response from
38
+ # the controller and then deciding based on them what goes into the
39
+ # #pipeline
40
+
41
+ def real_transform(controller, bound, file, action, *params)
42
+ alternate, path = file_template(params.last, controller) if params.size == 1 and action == 'index'
43
+ file_template, path = file_template(file, controller)
44
+ ctrl_template = render_action(controller, action, *params)
45
+
46
+ if chosen = to_transform = alternate || file_template || ctrl_template
47
+ pipeline(chosen, :binding => bound, :path => path)
48
+ else
49
+ raise Ramaze::Error::NoAction, "No Action found for `#{action}' on #{controller.class}"
50
+ end
51
+ end
52
+
53
+ # See if a string is an actual file.
54
+ #
55
+ # Answers with the contents and otherwise nil
56
+
57
+ def file_template action_or_file, controller
58
+ path =
59
+ if File.file?(action_or_file)
60
+ action_or_file
61
+ else
62
+ Controller.find_template(action_or_file, controller)
63
+ end
64
+
65
+ return File.read(path), path
66
+ rescue
67
+ nil
68
+ end
69
+
70
+ # Render an action, on a given controller with parameter
71
+
72
+ def render_action(controller, action, *params)
73
+ ctrl_template = controller.send(action, *params).to_s
74
+ rescue => ex
75
+ Informer.error(ex)
76
+ nil
77
+ end
78
+
79
+ # go through the pipeline and call #transform on every object found there,
80
+ # passing the template at that point.
81
+ # the order and contents of the pipeline are determined by an array
82
+ # in trait[:template_pipeline]
83
+ # the default being [Element, Morpher, self]
84
+ #
85
+ # TODO
86
+ # - put the pipeline into the Controller for use with all templates.
87
+
88
+ def pipeline(template, options = {})
89
+ transform_pipeline = ancestral_trait[:transform_pipeline]
90
+ opts = options.reject{|k,v| [:template, :path, :binding].all?{|o| k != o}}
91
+ opts[:pipeline] = :true
92
+
93
+ transform_pipeline.inject(template) do |memo, current|
94
+ current.transform(memo, opts)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,166 @@
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
+ # an Element is almost like an Controller, however, instead
5
+ # of connecting actions to templates it is only used in
6
+ # Ramaze::Template::Ezamar and can be used inside the
7
+ # templates of the Controller as a simple wrapper.
8
+ #
9
+ # Example:
10
+ #
11
+ # Your Element called Page:
12
+ #
13
+ # class Page < Ezamar::Element
14
+ # def render
15
+ # %{
16
+ # <html>
17
+ # <h1>
18
+ # #{@hash['title']}
19
+ # </h1>
20
+ # #{content}
21
+ # </html>
22
+ # }
23
+ # end
24
+ # end
25
+ #
26
+ # and one called SideBar
27
+ #
28
+ # class SideBar < Ezamar::Element
29
+ # def render
30
+ # %{
31
+ # <a href="http://something.com">something</a>
32
+ # }
33
+ # end
34
+ # end
35
+ #
36
+ # and your template (any template for any action):
37
+ #
38
+ # <Page title="Test">
39
+ # <SideBar />
40
+ # <p>
41
+ # Hello, World!
42
+ # </p>
43
+ # </Page>
44
+ #
45
+ # would result in:
46
+ #
47
+ # <html>
48
+ # <h1>
49
+ # Test
50
+ # </h1>
51
+ # <p>
52
+ # Hello, World!
53
+ # </p>
54
+ # </html>
55
+
56
+ class Ezamar::Element
57
+ attr_accessor :content
58
+
59
+ include Ramaze::Helper
60
+ extend Ramaze::Helper
61
+
62
+ helper :redirect, :link
63
+
64
+ # this will be called by #transform, passes along the
65
+ # stuff inside the tags for the element
66
+
67
+ def initialize(content)
68
+ @content = content
69
+ end
70
+
71
+ # The method that will be called upon to render the things
72
+ # inside the element, you can access #content from here, which
73
+ # contains the contents between the tags.
74
+ #
75
+ # It should answer with a String.
76
+
77
+ def render *args
78
+ @content
79
+ end
80
+
81
+ class << self
82
+ # transforms all <Element> tags within the string, takes also
83
+ # a binding to be compatible to the transform-pipeline, won't have
84
+ # any use for it though.
85
+ #
86
+ # It also sets a instance-variable for you called @hash, which
87
+ # contains the parameters you gave the <Element> tag.
88
+ # See above for an example of writing and using them.
89
+
90
+ def transform string = '', options = {}
91
+ binding, path = options.values_at(:binding, :path)
92
+ string = string.to_s
93
+ matches = string.scan(/<([A-Z][a-zA-Z0-9]*)(.*?)?>/)
94
+
95
+ matches.each do |(klass, params)|
96
+ transformer = (params[-1,1] == '/' ? :without : :with)
97
+ string = send("transform_#{transformer}_content", string, klass)
98
+ end
99
+ string
100
+ end
101
+
102
+ # transforms elements like:
103
+ # <Page> some content </Page>
104
+
105
+ def transform_with_content(string, klass)
106
+ string.gsub(/<#{klass}( .*?)?>(.*?)<\/#{klass}>/m) do |m|
107
+ params, content = $1.to_s, $2.to_s
108
+ finish_transform(klass, params, content)
109
+ end
110
+ end
111
+
112
+ # transforms elements like:
113
+ # <Page />
114
+
115
+ def transform_without_content(string, klass)
116
+ string.gsub(/<#{klass}( .*?)?\/>/) do |m|
117
+ params = $1.to_s
118
+ finish_transform(klass, params, content = '')
119
+ end
120
+ end
121
+
122
+ # find the element, create an instance, pass it the content
123
+ # check if it responds to :render and set an instance-variable
124
+ # called @hash to hold the parameters passed to the element.
125
+ #
126
+ # Parameters look like:
127
+ # <Page foo="true"> bar </Page>
128
+ # <Page foo="true" />
129
+
130
+ def finish_transform(klass, params, content)
131
+ instance = constant(klass).new(content)
132
+
133
+ hash = demunge_passed_variables(params)
134
+ instance.instance_variable_set("@hash", hash)
135
+
136
+ instance.render
137
+ rescue => ex
138
+ Ramaze::Informer.debug(ex.message)
139
+ ''
140
+ end
141
+
142
+ # basically processes stuff like
143
+ # 'foo="bar" foobar="baz"'
144
+ # do NOT pass actual objects that cannot be simply read as a string
145
+ # here, the information will be lost.
146
+ #
147
+ # Exceptions are true, false, Integers and Floats. They will appear
148
+ # in their real form (this again is also valid for strings that contain
149
+ # these values in a way that makes Integer/Float possible to parse them)
150
+ #
151
+ # Just remember, walk like a duck, talk like a duck.
152
+
153
+ def demunge_passed_variables(string)
154
+ string.scan(/\s?(.*?)="(.*?)"/).inject({}) do |hash, (key, value)|
155
+ value =
156
+ case value
157
+ when 'true' : true
158
+ when 'false' : false
159
+ else
160
+ Integer(value) rescue Float(value) rescue value
161
+ end
162
+ hash.merge key => value
163
+ end
164
+ end
165
+ end
166
+ end