merb 0.3.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +25 -26
- data/Rakefile +48 -36
- data/app_generators/merb/USAGE +5 -0
- data/app_generators/merb/merb_generator.rb +107 -0
- data/app_generators/merb/templates/Rakefile +99 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/controllers/application.rb +1 -1
- data/app_generators/merb/templates/app/controllers/exceptions.rb +13 -0
- data/{examples/skeleton/dist → app_generators/merb/templates}/app/helpers/global_helper.rb +0 -0
- data/{examples/skeleton/dist/app/mailers → app_generators/merb/templates/app/mailers/views}/layout/application.erb +0 -0
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +207 -0
- data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +38 -0
- data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +40 -0
- data/app_generators/merb/templates/app/views/layout/application.html.erb +11 -0
- data/app_generators/merb/templates/config/boot.rb +11 -0
- data/app_generators/merb/templates/config/dependencies.rb +41 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/development.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/production.rb +0 -0
- data/{examples/skeleton/dist/conf → app_generators/merb/templates/config}/environments/test.rb +0 -0
- data/app_generators/merb/templates/config/merb.yml +64 -0
- data/app_generators/merb/templates/config/merb_init.rb +16 -0
- data/app_generators/merb/templates/config/plugins.yml +1 -0
- data/app_generators/merb/templates/config/router.rb +32 -0
- data/{lib/merb/core_ext/merb_array.rb → app_generators/merb/templates/config/upload.conf} +0 -0
- data/app_generators/merb/templates/public/images/merb.jpg +0 -0
- data/app_generators/merb/templates/public/merb.fcgi +6 -0
- data/app_generators/merb/templates/public/stylesheets/master.css +119 -0
- data/app_generators/merb/templates/script/destroy +28 -0
- data/app_generators/merb/templates/script/generate +28 -0
- data/{examples/skeleton → app_generators/merb/templates}/script/stop_merb +0 -0
- data/app_generators/merb/templates/script/win_script.cmd +1 -0
- data/app_generators/merb/templates/spec/spec.opts +6 -0
- data/app_generators/merb/templates/spec/spec_helper.rb +10 -0
- data/app_generators/merb/templates/test/test_helper.rb +13 -0
- data/app_generators/merb_plugin/USAGE +5 -0
- data/app_generators/merb_plugin/merb_plugin_generator.rb +64 -0
- data/app_generators/merb_plugin/templates/LICENSE +20 -0
- data/app_generators/merb_plugin/templates/README +4 -0
- data/app_generators/merb_plugin/templates/Rakefile +35 -0
- data/app_generators/merb_plugin/templates/TODO +5 -0
- data/app_generators/merb_plugin/templates/merbtasks.rb +6 -0
- data/app_generators/merb_plugin/templates/sampleplugin.rb +10 -0
- data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +7 -0
- data/app_generators/merb_plugin/templates/spec_helper.rb +2 -0
- data/bin/merb +1 -1
- data/lib/autotest/discover.rb +3 -0
- data/lib/autotest/merb_rspec.rb +79 -0
- data/lib/merb.rb +72 -93
- data/lib/merb/{merb_abstract_controller.rb → abstract_controller.rb} +28 -5
- data/lib/merb/caching/action_cache.rb +65 -29
- data/lib/merb/caching/fragment_cache.rb +9 -4
- data/lib/merb/caching/store/file_cache.rb +22 -14
- data/lib/merb/caching/store/memory_cache.rb +26 -8
- data/lib/merb/{merb_constants.rb → constants.rb} +9 -7
- data/lib/merb/controller.rb +178 -0
- data/lib/merb/core_ext.rb +13 -11
- data/lib/merb/core_ext/array.rb +0 -0
- data/lib/merb/core_ext/{merb_class.rb → class.rb} +0 -0
- data/lib/merb/core_ext/{merb_enumerable.rb → enumerable.rb} +0 -0
- data/lib/merb/core_ext/get_args.rb +52 -0
- data/lib/merb/core_ext/{merb_hash.rb → hash.rb} +40 -11
- data/lib/merb/core_ext/{merb_inflections.rb → inflections.rb} +0 -0
- data/lib/merb/core_ext/{merb_inflector.rb → inflector.rb} +1 -1
- data/lib/merb/core_ext/{merb_kernel.rb → kernel.rb} +56 -3
- data/lib/merb/core_ext/mash.rb +88 -0
- data/lib/merb/core_ext/{merb_module.rb → module.rb} +0 -0
- data/lib/merb/core_ext/{merb_numeric.rb → numeric.rb} +0 -0
- data/lib/merb/core_ext/{merb_object.rb → object.rb} +10 -47
- data/lib/merb/core_ext/string.rb +56 -0
- data/lib/merb/core_ext/{merb_symbol.rb → symbol.rb} +0 -0
- data/lib/merb/dispatcher.rb +109 -0
- data/lib/merb/{merb_drb_server.rb → drb_server.rb} +0 -0
- data/lib/merb/erubis_ext.rb +10 -0
- data/lib/merb/exceptions.rb +173 -0
- data/lib/merb/generators/merb_app/merb_app.rb +5 -25
- data/lib/merb/generators/merb_generator_helpers.rb +317 -0
- data/lib/merb/generators/merb_plugin.rb +19 -0
- data/lib/merb/logger.rb +65 -0
- data/lib/merb/{merb_mail_controller.rb → mail_controller.rb} +102 -49
- data/lib/merb/{merb_mailer.rb → mailer.rb} +31 -27
- data/lib/merb/mixins/{basic_authentication_mixin.rb → basic_authentication.rb} +3 -3
- data/lib/merb/mixins/{controller_mixin.rb → controller.rb} +131 -112
- data/lib/merb/mixins/{erubis_capture_mixin.rb → erubis_capture.rb} +12 -21
- data/lib/merb/mixins/{form_control_mixin.rb → form_control.rb} +6 -12
- data/lib/merb/mixins/render.rb +401 -0
- data/lib/merb/mixins/responder.rb +378 -0
- data/lib/merb/mixins/{view_context_mixin.rb → view_context.rb} +65 -10
- data/lib/merb/mixins/web_controller.rb +29 -0
- data/lib/merb/{merb_handler.rb → mongrel_handler.rb} +59 -38
- data/lib/merb/part_controller.rb +19 -0
- data/lib/merb/plugins.rb +16 -0
- data/lib/merb/rack_adapter.rb +37 -0
- data/lib/merb/request.rb +421 -0
- data/lib/merb/router.rb +576 -0
- data/lib/merb/{merb_server.rb → server.rb} +275 -71
- data/lib/merb/session.rb +10 -10
- data/lib/merb/session/cookie_store.rb +125 -0
- data/lib/merb/session/{merb_mem_cache_session.rb → mem_cache_session.rb} +22 -9
- data/lib/merb/session/{merb_memory_session.rb → memory_session.rb} +15 -11
- data/lib/merb/template.rb +35 -8
- data/lib/merb/template/erubis.rb +16 -10
- data/lib/merb/template/haml.rb +33 -20
- data/lib/merb/template/markaby.rb +16 -14
- data/lib/merb/template/xml_builder.rb +8 -4
- data/lib/merb/test/{merb_fake_request.rb → fake_request.rb} +11 -5
- data/lib/merb/test/helper.rb +31 -0
- data/lib/merb/test/hpricot.rb +136 -0
- data/lib/merb/test/{merb_multipart.rb → multipart.rb} +1 -1
- data/lib/merb/test/rspec.rb +93 -0
- data/lib/merb/{merb_upload_handler.rb → upload_handler.rb} +5 -6
- data/lib/merb/{merb_upload_progress.rb → upload_progress.rb} +1 -1
- data/lib/merb/{merb_view_context.rb → view_context.rb} +27 -42
- data/lib/{merb_tasks.rb → tasks.rb} +0 -0
- data/lib/tasks/merb.rake +21 -11
- data/merb_default_generators/model/USAGE +0 -0
- data/merb_default_generators/model/model_generator.rb +16 -0
- data/merb_default_generators/model/templates/new_model_template.erb +5 -0
- data/merb_default_generators/resource_controller/USAGE +0 -0
- data/merb_default_generators/resource_controller/resource_controller_generator.rb +26 -0
- data/merb_default_generators/resource_controller/templates/controller.rb +30 -0
- data/merb_default_generators/resource_controller/templates/edit.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/helper.rb +5 -0
- data/merb_default_generators/resource_controller/templates/index.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/new.html.erb +1 -0
- data/merb_default_generators/resource_controller/templates/show.html.erb +1 -0
- data/merb_generators/controller/USAGE +5 -0
- data/merb_generators/controller/controller_generator.rb +16 -0
- data/merb_generators/controller/templates/controller.rb +8 -0
- data/merb_generators/controller/templates/helper.rb +5 -0
- data/merb_generators/controller/templates/index.html.erb +3 -0
- data/merb_generators/resource/USAGE +0 -0
- data/merb_generators/resource/resource_generator.rb +60 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +67 -0
- data/rspec_generators/merb_controller_test/templates/controller_spec.rb +8 -0
- data/rspec_generators/merb_controller_test/templates/edit_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/helper_spec.rb +5 -0
- data/rspec_generators/merb_controller_test/templates/index_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/new_spec.rb +12 -0
- data/rspec_generators/merb_controller_test/templates/show_spec.rb +5 -0
- data/rspec_generators/merb_model_test/merb_model_test_generator.rb +26 -0
- data/rspec_generators/merb_model_test/templates/model_spec_template.erb +7 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +53 -0
- data/test_unit_generators/merb_controller_test/templates/functional_test.rb +17 -0
- data/test_unit_generators/merb_controller_test/templates/helper_test.rb +9 -0
- data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +29 -0
- data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +9 -0
- metadata +172 -94
- data/examples/README_EXAMPLES +0 -10
- data/examples/skeleton/Rakefile +0 -68
- data/examples/skeleton/dist/app/views/layout/application.herb +0 -12
- data/examples/skeleton/dist/conf/database.yml +0 -23
- data/examples/skeleton/dist/conf/merb.yml +0 -57
- data/examples/skeleton/dist/conf/merb_init.rb +0 -24
- data/examples/skeleton/dist/conf/router.rb +0 -22
- data/examples/skeleton/dist/conf/upload.conf +0 -5
- data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +0 -14
- data/examples/skeleton/script/new_migration +0 -21
- data/lib/merb/core_ext/merb_string.rb +0 -18
- data/lib/merb/merb_controller.rb +0 -206
- data/lib/merb/merb_dispatcher.rb +0 -87
- data/lib/merb/merb_exceptions.rb +0 -319
- data/lib/merb/merb_part_controller.rb +0 -42
- data/lib/merb/merb_plugins.rb +0 -293
- data/lib/merb/merb_request.rb +0 -165
- data/lib/merb/merb_router.rb +0 -309
- data/lib/merb/merb_yaml_store.rb +0 -31
- data/lib/merb/mixins/render_mixin.rb +0 -283
- data/lib/merb/mixins/responder_mixin.rb +0 -159
- data/lib/merb/session/merb_ar_session.rb +0 -131
- data/lib/merb/vendor/paginator/README.txt +0 -84
- data/lib/merb/vendor/paginator/paginator.rb +0 -124
- 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 =
|
|
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 =
|
|
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
|
-
|
|
60
|
+
controller.thrown_content[name] << capture_erb( &block )
|
|
70
61
|
end
|
|
71
62
|
|
|
72
63
|
def block_content_for(name, &block)
|
|
73
|
-
|
|
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 #{
|
|
219
|
+
tag << %{<textarea #{o.html.to_xml_attributes }>#{o.value}</textarea>}
|
|
221
220
|
end
|
|
222
221
|
|
|
223
222
|
def date(o)
|
|
224
|
-
o.value
|
|
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
|
|
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 #{
|
|
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 #{
|
|
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
|