merb 0.3.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. data/README +25 -26
  2. data/Rakefile +48 -36
  3. data/app_generators/merb/USAGE +5 -0
  4. data/app_generators/merb/merb_generator.rb +107 -0
  5. data/app_generators/merb/templates/Rakefile +99 -0
  6. data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
  7. data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
  8. data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
  9. data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
  10. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
  11. data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
  12. data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
  13. data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
  14. data/app_generators/merb/templates/config/boot.rb +11 -0
  15. data/app_generators/merb/templates/config/dependencies.rb +41 -0
  16. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
  17. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
  18. data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
  19. data/app_generators/merb/templates/config/merb.yml +64 -0
  20. data/app_generators/merb/templates/config/merb_init.rb +16 -0
  21. data/app_generators/merb/templates/config/plugins.yml +1 -0
  22. data/app_generators/merb/templates/config/router.rb +32 -0
  23. data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
  24. data/app_generators/merb/templates/public/images/merb.jpg +0 -0
  25. data/app_generators/merb/templates/public/merb.fcgi +6 -0
  26. data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
  27. data/app_generators/merb/templates/script/destroy +28 -0
  28. data/app_generators/merb/templates/script/generate +28 -0
  29. data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
  30. data/app_generators/merb/templates/script/win_script.cmd +1 -0
  31. data/app_generators/merb/templates/spec/spec.opts +6 -0
  32. data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
  33. data/app_generators/merb/templates/test/test_helper.rb +13 -0
  34. data/app_generators/merb_plugin/USAGE +5 -0
  35. data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
  36. data/app_generators/merb_plugin/templates/LICENSE +20 -0
  37. data/app_generators/merb_plugin/templates/README +4 -0
  38. data/app_generators/merb_plugin/templates/Rakefile +35 -0
  39. data/app_generators/merb_plugin/templates/TODO +5 -0
  40. data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
  41. data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
  42. data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
  43. data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
  44. data/bin/merb +1 -1
  45. data/lib/autotest/discover.rb +3 -0
  46. data/lib/autotest/merb_rspec.rb +79 -0
  47. data/lib/merb.rb +72 -93
  48. data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
  49. data/lib/merb/caching/action_cache.rb +65 -29
  50. data/lib/merb/caching/fragment_cache.rb +9 -4
  51. data/lib/merb/caching/store/file_cache.rb +22 -14
  52. data/lib/merb/caching/store/memory_cache.rb +26 -8
  53. data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
  54. data/lib/merb/controller.rb +178 -0
  55. data/lib/merb/core_ext.rb +13 -11
  56. data/lib/merb/core_ext/array.rb +0 -0
  57. data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
  58. data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
  59. data/lib/merb/core_ext/get_args.rb +52 -0
  60. data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
  61. data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
  62. data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
  63. data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
  64. data/lib/merb/core_ext/mash.rb +88 -0
  65. data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
  66. data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
  67. data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
  68. data/lib/merb/core_ext/string.rb +56 -0
  69. data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
  70. data/lib/merb/dispatcher.rb +109 -0
  71. data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
  72. data/lib/merb/erubis_ext.rb +10 -0
  73. data/lib/merb/exceptions.rb +173 -0
  74. data/lib/merb/generators/merb_app/merb_app.rb +5 -25
  75. data/lib/merb/generators/merb_generator_helpers.rb +317 -0
  76. data/lib/merb/generators/merb_plugin.rb +19 -0
  77. data/lib/merb/logger.rb +65 -0
  78. data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
  79. data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
  80. data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
  81. data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
  82. data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
  83. data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
  84. data/lib/merb/mixins/render.rb +401 -0
  85. data/lib/merb/mixins/responder.rb +378 -0
  86. data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
  87. data/lib/merb/mixins/web_controller.rb +29 -0
  88. data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
  89. data/lib/merb/part_controller.rb +19 -0
  90. data/lib/merb/plugins.rb +16 -0
  91. data/lib/merb/rack_adapter.rb +37 -0
  92. data/lib/merb/request.rb +421 -0
  93. data/lib/merb/router.rb +576 -0
  94. data/lib/merb/{merb_server.rb → server.rb} +275 -71
  95. data/lib/merb/session.rb +10 -10
  96. data/lib/merb/session/cookie_store.rb +125 -0
  97. data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
  98. data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
  99. data/lib/merb/template.rb +35 -8
  100. data/lib/merb/template/erubis.rb +16 -10
  101. data/lib/merb/template/haml.rb +33 -20
  102. data/lib/merb/template/markaby.rb +16 -14
  103. data/lib/merb/template/xml_builder.rb +8 -4
  104. data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
  105. data/lib/merb/test/helper.rb +31 -0
  106. data/lib/merb/test/hpricot.rb +136 -0
  107. data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
  108. data/lib/merb/test/rspec.rb +93 -0
  109. data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
  110. data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
  111. data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
  112. data/lib/{merb_tasks.rb → tasks.rb} +0 -0
  113. data/lib/tasks/merb.rake +21 -11
  114. data/merb_default_generators/model/USAGE +0 -0
  115. data/merb_default_generators/model/model_generator.rb +16 -0
  116. data/merb_default_generators/model/templates/new_model_template.erb +5 -0
  117. data/merb_default_generators/resource_controller/USAGE +0 -0
  118. data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
  119. data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
  120. data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
  121. data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
  122. data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
  123. data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
  124. data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
  125. data/merb_generators/controller/USAGE +5 -0
  126. data/merb_generators/controller/controller_generator.rb +16 -0
  127. data/merb_generators/controller/templates/controller.rb +8 -0
  128. data/merb_generators/controller/templates/helper.rb +5 -0
  129. data/merb_generators/controller/templates/index.html.erb +3 -0
  130. data/merb_generators/resource/USAGE +0 -0
  131. data/merb_generators/resource/resource_generator.rb +60 -0
  132. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
  133. data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
  134. data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
  135. data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
  136. data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
  137. data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
  138. data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
  139. data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
  140. data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
  141. data/script/destroy +14 -0
  142. data/script/generate +14 -0
  143. data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
  144. data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
  145. data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
  146. data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
  147. data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
  148. metadata +172 -94
  149. data/examples/README_EXAMPLES +0 -10
  150. data/examples/skeleton/Rakefile +0 -68
  151. data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
  152. data/examples/skeleton/dist/conf/database.yml +0 -23
  153. data/examples/skeleton/dist/conf/merb.yml +0 -57
  154. data/examples/skeleton/dist/conf/merb_init.rb +0 -24
  155. data/examples/skeleton/dist/conf/router.rb +0 -22
  156. data/examples/skeleton/dist/conf/upload.conf +0 -5
  157. data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
  158. data/examples/skeleton/script/new_migration +0 -21
  159. data/lib/merb/core_ext/merb_string.rb +0 -18
  160. data/lib/merb/merb_controller.rb +0 -206
  161. data/lib/merb/merb_dispatcher.rb +0 -87
  162. data/lib/merb/merb_exceptions.rb +0 -319
  163. data/lib/merb/merb_part_controller.rb +0 -42
  164. data/lib/merb/merb_plugins.rb +0 -293
  165. data/lib/merb/merb_request.rb +0 -165
  166. data/lib/merb/merb_router.rb +0 -309
  167. data/lib/merb/merb_yaml_store.rb +0 -31
  168. data/lib/merb/mixins/render_mixin.rb +0 -283
  169. data/lib/merb/mixins/responder_mixin.rb +0 -159
  170. data/lib/merb/session/merb_ar_session.rb +0 -131
  171. data/lib/merb/vendor/paginator/README.txt +0 -84
  172. data/lib/merb/vendor/paginator/paginator.rb +0 -124
  173. data/lib/tasks/db.rake +0 -55
@@ -1,6 +1,14 @@
1
1
  module Merb
2
+
3
+
2
4
 
3
5
  module ErubisCaptureMixin
6
+
7
+ # Provides direct acccess to the buffer for this view context
8
+ def _buffer( the_binding )
9
+ @_buffer ||= eval( "_buf", the_binding )
10
+ end
11
+
4
12
  # Capture allows you to extract a part of the template into an
5
13
  # instance variable. You can use this instance variable anywhere
6
14
  # in your templates and even in your layout.
@@ -13,7 +21,7 @@ module Merb
13
21
  def capture(*args, &block)
14
22
  # execute the block
15
23
  begin
16
- buffer = eval("_buf", block.binding)
24
+ buffer = _buffer( block.binding )
17
25
  rescue
18
26
  buffer = nil
19
27
  end
@@ -24,23 +32,6 @@ module Merb
24
32
  capture_erb_with_buffer(buffer, *args, &block)
25
33
  end
26
34
  end
27
-
28
- # Calling throw_content stores the block of markup for later use.
29
- # Subsequently, you can make calls to it by name with <tt>catch_content</tt>
30
- # in another template or in the layout.
31
- #
32
- # Example:
33
- #
34
- # <% throw_content :header do %>
35
- # alert('hello world')
36
- # <% end %>
37
- #
38
- # You can use catch_content :header anywhere in your templates.
39
- #
40
- # <%= catch_content :header %>
41
- def throw_content(name, content = nil, &block)
42
- eval "@_#{name}_content = (@_#{name}_content || '') + capture(&block)"
43
- end
44
35
 
45
36
  private
46
37
  def capture_block(*args, &block)
@@ -48,7 +39,7 @@ module Merb
48
39
  end
49
40
 
50
41
  def capture_erb(*args, &block)
51
- buffer = eval("_buf", block.binding)
42
+ buffer = _buffer
52
43
  capture_erb_with_buffer(buffer, *args, &block)
53
44
  end
54
45
 
@@ -66,11 +57,11 @@ module Merb
66
57
  end
67
58
 
68
59
  def erb_content_for(name, &block)
69
- eval "@_#{name}_content = (@_#{name}_content|| '') + capture_erb(&block)"
60
+ controller.thrown_content[name] << capture_erb( &block )
70
61
  end
71
62
 
72
63
  def block_content_for(name, &block)
73
- eval "@_#{name}_content = (@_#{name}_content|| '') + capture_block(&block)"
64
+ controller.thrown_content[name] << capture_block( &block )
74
65
  end
75
66
  end
76
67
 
@@ -156,7 +156,6 @@ module Merb
156
156
  # </optgroup>
157
157
  # </select>
158
158
  #
159
-
160
159
 
161
160
  def control_for( obj, meth, type, opts = {} )
162
161
  instance = obj
@@ -217,11 +216,11 @@ module Merb
217
216
  def textarea(o)
218
217
  tag = ''
219
218
  tag << label_for_object( o )
220
- tag << %{<textarea #{options_as_attributes( o.html ) }>#{o.value}</textarea>}
219
+ tag << %{<textarea #{o.html.to_xml_attributes }>#{o.value}</textarea>}
221
220
  end
222
221
 
223
222
  def date(o)
224
- o.value ||= Date.today
223
+ o.value = Date.today unless (o.value.is_a? Time or o.value.is_a? Date or o.value.is_a? DateTime)
225
224
  selects = []
226
225
  selects << label_for_object( o )
227
226
  selects << date_day(o.temp(:value => o.value.day))
@@ -231,7 +230,7 @@ module Merb
231
230
  end
232
231
 
233
232
  def time(o)
234
- o.value ||= Time.now
233
+ o.value = Time.now unless (o.value.is_a? Time or o.value.is_a? DateTime)
235
234
  selects = []
236
235
  selects << label_for_object( o )
237
236
  selects << date_day(o.temp(:value => o.value.day))
@@ -257,14 +256,14 @@ module Merb
257
256
  end
258
257
  out = ""
259
258
  out << label_for_object( o )
260
- out << %{<select #{options_as_attributes( o.html )}>}
259
+ out << %{<select #{o.html.to_xml_attributes }>}
261
260
  out << %{#{options_for_select( o.obj, o.meth, options )}}
262
261
  out << %{</select>}
263
262
  end
264
263
 
265
264
  # Creates an input tag with the given +option+ hash as xml/html attributes
266
265
  def input_tag( options )
267
- %{<input #{options_as_attributes( options ) }/>}
266
+ %{<input #{options.to_xml_attributes }/>}
268
267
  end
269
268
 
270
269
  # Creates an select tag that is not nesiscarily bound to an objects value
@@ -286,12 +285,7 @@ module Merb
286
285
  # Creates a label from the openstruct created in control_for
287
286
  def label_for_object( o )
288
287
  o.label.nil? ? "" : %{<label for="#{o.html[:id]}">#{o.label}</label>}
289
- end
290
-
291
- # Converts a hash to use as attributes in an xml/html tag
292
- def options_as_attributes( options )
293
- options ? options.map{ |k,v| "#{k}=\"#{v}\""}.join( ' ' ) : nil
294
- end
288
+ end
295
289
 
296
290
  # The gateway to creating options for a select box
297
291
  def options_for_select( obj, value_method, options )
@@ -0,0 +1,401 @@
1
+ module Merb
2
+
3
+ module RenderMixin
4
+ @@cached_templates = {}
5
+ include Merb::ControllerExceptions
6
+
7
+ def self.included(base)
8
+ base.class_eval {
9
+ class_inheritable_accessor :_template_root,
10
+ :_layout
11
+
12
+ self._layout = :application
13
+ self._template_root = File.expand_path(MERB_VIEW_ROOT)
14
+
15
+ attr_accessor :template
16
+ }
17
+ end
18
+
19
+ # Universal render method. Template handlers are registered
20
+ # by template extension. So you can use the same render method
21
+ # for any kind of template that implements an adapter module.
22
+ #
23
+ # Out of the box Merb supports Erubis. In addition, Haml, Markaby
24
+ # and Builder templates are built in, but you must activate them in
25
+ # merb_init.rb by listing the name of the template engine you
26
+ # want to use:
27
+ #
28
+ # Merb::Template::Haml
29
+ #
30
+ # In addition, you can identify the type of output with an
31
+ # extension in the middle of the filename. Erubis is capable of
32
+ # rendering any kind of text output, not just HTML.
33
+ # This is the recommended usage.
34
+ #
35
+ # index.html.erb update.js.erb feed.xml.erb
36
+ #
37
+ # Examples:
38
+ #
39
+ # render
40
+ #
41
+ # Looks for views/controllername/actionname.* and renders
42
+ # the template with the proper engine based on its file extension.
43
+ #
44
+ # render :layout => :none
45
+ #
46
+ # Renders the current template with no layout. XMl Builder templates
47
+ # are exempt from layout by default.
48
+ #
49
+ # render :action => 'foo'
50
+ #
51
+ # Renders views/controllername/foo.*
52
+ #
53
+ # render :nothing => 200
54
+ #
55
+ # Renders nothing with a status of 200
56
+ #
57
+ # render :template => 'shared/message'
58
+ #
59
+ # Renders views/shared/message
60
+ #
61
+ # render :js => "$('some-div').toggle();"
62
+ #
63
+ # If the right hand side of :js => is a string then the proper
64
+ # javascript headers will be set and the string will be returned
65
+ # verbatim as js.
66
+ #
67
+ # render :js => :spinner
68
+ #
69
+ # When the rhs of :js => is a Symbol, it will be used as the
70
+ # action/template name so: views/controllername/spinner.js.erb
71
+ # will be rendered as javascript
72
+ #
73
+ # render :js => true
74
+ #
75
+ # This will just look for the current controller/action template
76
+ # with the .js.erb extension and render it as javascript
77
+ #
78
+ # XML can be rendered with the same options as Javascript, but it
79
+ # also accepts the :template option. This allows you to use any
80
+ # template engine to render XML.
81
+ #
82
+ # render :xml => @posts.to_xml
83
+ # render :xml => "<foo><bar>Hi!</bar></foo>"
84
+ #
85
+ # This will set the appropriate xml headers and render the rhs
86
+ # of :xml => as a string. SO you can pass any xml string to this
87
+ # to be rendered.
88
+ #
89
+ # render :xml => :hello
90
+ #
91
+ # Renders the hello.xrb template for the current controller.
92
+ #
93
+ # render :xml => true
94
+ # render :xml => true, :action => "buffalo"
95
+ #
96
+ # Renders the buffalo.xml.builder or buffalo.xerb template for the current controller.
97
+ #
98
+ # render :xml=>true, :template => 'foo/bar'
99
+ #
100
+ # Renders the the foo/bar template. This is not limited to
101
+ # the default rxml, xerb, or builder templates, but could
102
+ # just as easy be HAML.
103
+ #
104
+ # Render also supports passing in an object
105
+ # ===Example
106
+ #
107
+ # class People < Application
108
+ # provides :xml
109
+ #
110
+ # def index
111
+ # @people = User.all
112
+ # render @people
113
+ # end
114
+ # end
115
+ #
116
+ # This will first check to see if a index.xml.* template extists, if not
117
+ # it will call @people.to_xml (as defined in the add_mime_type method) on the passed
118
+ # in object if such a method exists for the current content_type
119
+ #
120
+ # When using multiple calls to render in one action, the context of the render is cached for performance reasons
121
+ # That is, all instance variables are loaded into the view_context object only on the first call and then this is re-used.
122
+ # What this means is that in the case where you may want to render then set some more instance variables and then call render again
123
+ # you will want to use a clean context object. To do this
124
+ #
125
+ # render :clean_context => true
126
+ #
127
+ # This will ensure that all instance variable are up to date in your views.
128
+ #
129
+ def render(*args,&blk)
130
+ opts = Hash === args.last ? args.pop : {}
131
+
132
+ action = opts[:action] || params[:action]
133
+ opts[:layout] ||= _layout
134
+
135
+ choose_template_format(Merb.available_mime_types, opts)
136
+
137
+ # Handles the case where render is called with an object
138
+ if obj = args.first
139
+ # Check for a template
140
+ unless find_template({:action => action}.merge(opts))
141
+ fmt = content_type
142
+ if transform_method = Merb.mime_transform_method(fmt)
143
+ set_response_headers fmt
144
+ return obj.send(transform_method)
145
+ end
146
+ end
147
+ end
148
+
149
+ case
150
+ when status = opts[:nothing]
151
+ return render_nothing(status)
152
+
153
+ when partial = opts[:partial]
154
+ opts[:format] ||= :html
155
+ template = find_partial(partial, opts)
156
+ opts[:layout] = :none
157
+
158
+ # Add an instance variable that can be used to create the locals in the
159
+ # partial
160
+ if opts[:locals]
161
+ @_merb_partial_locals = opts[:locals]
162
+ end
163
+ opts[:clean_context] = true
164
+
165
+ when opts[:inline]
166
+ text = opts.delete(:inline)
167
+ return render_inline(text, opts)
168
+ else
169
+ set_response_headers @_template_format
170
+
171
+ case @_format_value
172
+ when String
173
+ return @_format_value
174
+ when Symbol
175
+ if !Merb.available_mime_types.keys.include?(@_format_value) # render :js => "Some js value"
176
+ template = find_template(:action => @_format_value)
177
+ else
178
+ if opts[@_format_value] == @_format_value # An edge case that lives in the specs
179
+ # says that a render :js => :js should be catered for
180
+ template = find_template(:action => @_format_value)
181
+ else
182
+ # when called from within an action as plain render within a respond_to block
183
+ template = find_template(opts.merge( :action => action ))
184
+ end
185
+ end
186
+ else
187
+ if template = opts[:template]
188
+ # render :template => "this_template"
189
+ template = find_template( :template => template)
190
+ else
191
+ # a plain action render
192
+ # def index; render; end
193
+ template = find_template(:action => action)
194
+ end
195
+ end
196
+ end
197
+
198
+ unless template
199
+ raise TemplateNotFound, "No template matched at #{unmatched}"
200
+ end
201
+ self.template ||= File.basename(template)
202
+
203
+ engine = Template.engine_for(template)
204
+ options = {
205
+ :file => template,
206
+ :view_context => (opts[:clean_context] ? clean_view_context(engine) : cached_view_context(engine)),
207
+ :opts => opts
208
+ }
209
+ content = engine.transform(options)
210
+ if engine.exempt_from_layout? || opts[:layout] == :none || [:js].include?(@_template_format)
211
+ content
212
+ else
213
+ wrap_layout(content, opts)
214
+ end
215
+ end
216
+
217
+ def set_response_headers(tmpl_fmt)
218
+ if self.respond_to?(:headers)
219
+ # Set the headers
220
+ headers['Content-Type'] = Merb.available_mime_types[tmpl_fmt].first
221
+
222
+ # set any additinal headers that may be associated with the current mime type
223
+ Merb.response_headers[tmpl_fmt].each do |key,value|
224
+ headers[key.to_s] = value
225
+ end if Merb.response_headers[tmpl_fmt]
226
+
227
+ end
228
+ end
229
+
230
+ def render_inline(text, opts)
231
+ # Does not yet support format selection in the wrap_layout
232
+ # Needs to get the template format need a spec for this
233
+ # should be
234
+ choose_template_format(Merb.available_mime_types, opts)
235
+
236
+ engine = Template.engine_for_extension(opts[:extension] || 'erb')
237
+ options = {
238
+ :text => text,
239
+ :view_context => (opts[:clean_context] ? clean_view_context(engine) : cached_view_context(engine)),
240
+ :opts => opts
241
+ }
242
+ content = engine.transform(options)
243
+ if engine.exempt_from_layout? || opts[:layout] == :none
244
+ content
245
+ else
246
+ wrap_layout(content, opts)
247
+ end
248
+ end
249
+
250
+ # does a render with no layout. Also sets the
251
+ # content type header to text/javascript. Use
252
+ # this when you want to render a template with
253
+ # .jerb extension.
254
+ def render_js(template=nil)
255
+ render :js => true, :action => (template || params[:action])
256
+ end
257
+
258
+ # renders nothing but sets the status, defaults
259
+ # to 200. does send one ' ' space char, this is for
260
+ # safari and flash uploaders to work.
261
+ def render_nothing(status=200)
262
+ @_status = status
263
+ return " "
264
+ end
265
+
266
+ def set_status(status)
267
+ @_status = status
268
+ end
269
+
270
+ def render_no_layout(opts={})
271
+ render opts.update({:layout => :none})
272
+ end
273
+
274
+ # This is merb's partial render method. You name your
275
+ # partials _partialname.format.* , and then call it like
276
+ # partial(:partialname). If there is no '/' character
277
+ # in the argument passed in it will look for the partial
278
+ # in the view directory that corresponds to the current
279
+ # controller name. If you pass a string with a path in it
280
+ # you can render partials in other view directories. So
281
+ # if you create a views/shared directory then you can call
282
+ # partials that live there like partial('shared/foo')
283
+ def partial(template, locals={})
284
+ options = {:partial => template, :locals => locals}
285
+ options.merge!(:format => @_template_format) if @_template_format
286
+ render options
287
+ end
288
+
289
+ # +catch_content+ catches the thrown content from another template
290
+ # So when you throw_content(:foo) {...} you can catch_content :foo
291
+ # in another view or the layout.
292
+ def catch_content(name)
293
+ thrown_content[name]
294
+ end
295
+
296
+ private
297
+
298
+ # this returns a ViewContext object populated with all
299
+ # the instance variables in your controller. This is used
300
+ # as the view context object for the Erubis templates.
301
+ def cached_view_context(engine=nil)
302
+ @_view_context_cache ||= clean_view_context(engine)
303
+ end
304
+
305
+ def clean_view_context(engine=nil)
306
+ if engine.nil?
307
+ ::Merb::ViewContext.new(self)
308
+ else
309
+ engine.view_context_klass.new(self)
310
+ end
311
+ end
312
+
313
+ def wrap_layout(content, opts={})
314
+ @_template_format ||= choose_template_format(Merb.available_mime_types, opts)
315
+
316
+ if opts[:layout] != :application
317
+ layout_choice = find_template(:layout => opts[:layout])
318
+ else
319
+ if name = find_template(:layout => self.class.name.snake_case.split('::').join('/'))
320
+ layout_choice = name
321
+ else
322
+ previous_glob = unmatched
323
+ layout_choice = find_template(:layout => :application)
324
+ end
325
+ end
326
+ unless layout_choice
327
+ raise LayoutNotFound, "No layout matched #{unmatched}#{" or #{previous_glob}" if previous_glob}"
328
+ end
329
+
330
+ thrown_content[:layout] = content
331
+ engine = Template.engine_for(layout_choice)
332
+ options = {
333
+ :file => layout_choice,
334
+ :view_context => cached_view_context,
335
+ :opts => opts
336
+ }
337
+ engine.transform(options)
338
+ end
339
+
340
+ # OPTIMIZE : combine find_template and find_partial ?
341
+ def find_template(opts={})
342
+ if template = opts[:template]
343
+ path = _template_root / template
344
+ elsif action = opts[:action]
345
+ segment = self.class.name.snake_case.split('::').join('/')
346
+ path = _template_root / segment / action
347
+ elsif _layout = opts[:layout]
348
+ path = _template_root / 'layout' / _layout
349
+ else
350
+ raise "called find_template without an :action or :layout"
351
+ end
352
+ glob_template(path, opts)
353
+ end
354
+
355
+ def find_partial(template, opts={})
356
+ if template =~ /\//
357
+ t = template.split('/')
358
+ template = t.pop
359
+ path = _template_root / t.join('/') / "_#{template}"
360
+ else
361
+ segment = self.class.name.snake_case.split('::').join('/')
362
+ path = _template_root / segment / "_#{template}"
363
+ end
364
+ glob_template(path, opts)
365
+ end
366
+
367
+ # This method will return a matching template at the specified path, first using the
368
+ # template_name.format.engine convention and if that fails, it falls back to the old
369
+ # style extensions (herb, jerb etc)
370
+ def glob_template(path, opts = {})
371
+ extensions = Template::EXTENSIONS.keys
372
+ glob = "#{path}.#{@_template_format}.{#{opts[:ext] || extensions.join(",")}}"
373
+ Dir[glob].first || (@_merb_unmatched = glob; nil)
374
+ end
375
+
376
+ # Chooses the format of the template based on the params hash or the explicit
377
+ # request of the developer.
378
+ def choose_template_format(types, opts)
379
+ opts[:format] ||= content_type
380
+ @_template_format = [(opts.keys & types.keys)].flatten.first # Check for render :js => etc
381
+ @_template_format ||= opts[:format] || :html
382
+ @_format_value = opts[@_template_format] || opts[:format] # get the value of the option if something
383
+ # like :js was used
384
+
385
+ # need to change things to symbols so as not to stuff up part controllers
386
+ if @_template_format.to_s == @_format_value.to_s
387
+ @_template_format = @_template_format.to_sym
388
+ @_format_value = @_format_value.to_sym
389
+ end
390
+
391
+ @_template_format
392
+ end
393
+
394
+ # For the benefit of error handlers, returns the most recent glob
395
+ # pattern which didn't find a file in the filesystem
396
+ def unmatched
397
+ @_merb_unmatched
398
+ end
399
+
400
+ end
401
+ end