merb 0.5.3 → 0.9.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +0 -20
- data/README +0 -277
- data/Rakefile +80 -199
- data/TODO +0 -3
- metadata +19 -438
- data/SVN_REVISION +0 -1
- data/app_generators/merb/USAGE +0 -5
- data/app_generators/merb/merb_generator.rb +0 -108
- data/app_generators/merb/templates/Rakefile +0 -124
- data/app_generators/merb/templates/app/controllers/application.rb +0 -3
- data/app_generators/merb/templates/app/controllers/exceptions.rb +0 -13
- data/app_generators/merb/templates/app/helpers/global_helper.rb +0 -5
- data/app_generators/merb/templates/app/mailers/views/layout/application.html.erb +0 -1
- data/app_generators/merb/templates/app/mailers/views/layout/application.text.erb +0 -1
- data/app_generators/merb/templates/app/parts/views/layout/application.html.erb +0 -1
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +0 -216
- data/app_generators/merb/templates/app/views/exceptions/not_acceptable.html.erb +0 -38
- data/app_generators/merb/templates/app/views/exceptions/not_found.html.erb +0 -40
- data/app_generators/merb/templates/app/views/layout/application.html.erb +0 -11
- data/app_generators/merb/templates/config/boot.rb +0 -11
- data/app_generators/merb/templates/config/dependencies.rb +0 -41
- data/app_generators/merb/templates/config/environments/development.rb +0 -1
- data/app_generators/merb/templates/config/environments/production.rb +0 -1
- data/app_generators/merb/templates/config/environments/test.rb +0 -1
- data/app_generators/merb/templates/config/merb.yml +0 -82
- data/app_generators/merb/templates/config/merb_init.rb +0 -17
- data/app_generators/merb/templates/config/plugins.yml +0 -1
- data/app_generators/merb/templates/config/router.rb +0 -35
- data/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 +0 -6
- data/app_generators/merb/templates/public/stylesheets/master.css +0 -119
- data/app_generators/merb/templates/script/destroy +0 -32
- data/app_generators/merb/templates/script/generate +0 -32
- data/app_generators/merb/templates/script/stop_merb +0 -13
- data/app_generators/merb/templates/script/win_script.cmd +0 -1
- data/app_generators/merb/templates/spec/spec.opts +0 -6
- data/app_generators/merb/templates/spec/spec_helper.rb +0 -15
- data/app_generators/merb/templates/test/test_helper.rb +0 -14
- data/app_generators/merb_plugin/USAGE +0 -5
- data/app_generators/merb_plugin/merb_plugin_generator.rb +0 -68
- data/app_generators/merb_plugin/templates/LICENSE +0 -20
- data/app_generators/merb_plugin/templates/README +0 -4
- data/app_generators/merb_plugin/templates/Rakefile +0 -35
- data/app_generators/merb_plugin/templates/TODO +0 -5
- data/app_generators/merb_plugin/templates/merbtasks.rb +0 -6
- data/app_generators/merb_plugin/templates/sampleplugin.rb +0 -10
- data/app_generators/merb_plugin/templates/sampleplugin_spec.rb +0 -7
- data/app_generators/merb_plugin/templates/spec_helper.rb +0 -2
- data/bin/merb +0 -4
- data/lib/autotest/discover.rb +0 -3
- data/lib/autotest/merb_rspec.rb +0 -80
- data/lib/merb.rb +0 -188
- data/lib/merb/abstract_controller.rb +0 -399
- data/lib/merb/assets.rb +0 -160
- data/lib/merb/assets.rb.orig +0 -119
- data/lib/merb/boot_loader.rb +0 -286
- data/lib/merb/boot_loader.rb.orig +0 -235
- data/lib/merb/caching.rb +0 -5
- data/lib/merb/caching/action_cache.rb +0 -92
- data/lib/merb/caching/fragment_cache.rb +0 -39
- data/lib/merb/caching/store/file_cache.rb +0 -90
- data/lib/merb/caching/store/memory_cache.rb +0 -85
- data/lib/merb/config.rb +0 -290
- data/lib/merb/constants.rb +0 -50
- data/lib/merb/controller.rb +0 -220
- data/lib/merb/cookies.rb +0 -95
- data/lib/merb/core_ext.rb +0 -15
- data/lib/merb/core_ext/array.rb +0 -0
- data/lib/merb/core_ext/class.rb +0 -180
- data/lib/merb/core_ext/enumerable.rb +0 -49
- data/lib/merb/core_ext/get_args.rb +0 -76
- data/lib/merb/core_ext/hash.rb +0 -306
- data/lib/merb/core_ext/inflections.rb +0 -112
- data/lib/merb/core_ext/inflector.rb +0 -275
- data/lib/merb/core_ext/kernel.rb +0 -242
- data/lib/merb/core_ext/mash.rb +0 -88
- data/lib/merb/core_ext/module.rb +0 -67
- data/lib/merb/core_ext/numeric.rb +0 -72
- data/lib/merb/core_ext/object.rb +0 -183
- data/lib/merb/core_ext/string.rb +0 -53
- data/lib/merb/core_ext/symbol.rb +0 -6
- data/lib/merb/dispatcher.rb +0 -109
- data/lib/merb/drb_server.rb +0 -19
- data/lib/merb/erubis_ext.rb +0 -10
- data/lib/merb/exceptions.rb +0 -192
- data/lib/merb/generators/merb_app/merb_app.rb +0 -22
- data/lib/merb/generators/merb_generator_helpers.rb +0 -318
- data/lib/merb/generators/merb_plugin.rb +0 -22
- data/lib/merb/logger.rb +0 -78
- data/lib/merb/mail_controller.rb +0 -268
- data/lib/merb/mailer.rb +0 -87
- data/lib/merb/mixins/basic_authentication.rb +0 -35
- data/lib/merb/mixins/controller.rb +0 -160
- data/lib/merb/mixins/erubis_capture.rb +0 -68
- data/lib/merb/mixins/general_controller.rb +0 -253
- data/lib/merb/mixins/inline_partial.rb +0 -32
- data/lib/merb/mixins/render.rb +0 -465
- data/lib/merb/mixins/responder.rb +0 -449
- data/lib/merb/mixins/view_context.rb +0 -558
- data/lib/merb/mixins/web_controller.rb +0 -36
- data/lib/merb/mongrel_handler.rb +0 -168
- data/lib/merb/part_controller.rb +0 -29
- data/lib/merb/plugins.rb +0 -16
- data/lib/merb/rack_adapter.rb +0 -37
- data/lib/merb/request.rb +0 -465
- data/lib/merb/router.rb +0 -646
- data/lib/merb/server.rb +0 -169
- data/lib/merb/session.rb +0 -23
- data/lib/merb/session/cookie_store.rb +0 -118
- data/lib/merb/session/mem_cache_session.rb +0 -131
- data/lib/merb/session/memory_session.rb +0 -176
- data/lib/merb/template.rb +0 -37
- data/lib/merb/template/erubis.rb +0 -68
- data/lib/merb/template/haml.rb +0 -87
- data/lib/merb/template/markaby.rb +0 -59
- data/lib/merb/template/xml_builder.rb +0 -50
- data/lib/merb/test/fake_request.rb +0 -74
- data/lib/merb/test/helper.rb +0 -260
- data/lib/merb/test/hpricot.rb +0 -136
- data/lib/merb/test/multipart.rb +0 -66
- data/lib/merb/test/rspec.rb +0 -18
- data/lib/merb/test/rspec_matchers/controller_matchers.rb +0 -117
- data/lib/merb/test/rspec_matchers/markup_matchers.rb +0 -98
- data/lib/merb/upload_handler.rb +0 -80
- data/lib/merb/upload_progress.rb +0 -48
- data/lib/merb/version.rb +0 -49
- data/lib/merb/view_context.rb +0 -79
- data/lib/tasks.rb +0 -7
- data/lib/tasks/merb.rake +0 -54
- data/merb_default_generators/model/USAGE +0 -0
- data/merb_default_generators/model/model_generator.rb +0 -16
- data/merb_default_generators/model/templates/new_model_template.erb +0 -5
- data/merb_default_generators/resource_controller/USAGE +0 -0
- data/merb_default_generators/resource_controller/resource_controller_generator.rb +0 -26
- data/merb_default_generators/resource_controller/templates/controller.rb +0 -30
- data/merb_default_generators/resource_controller/templates/edit.html.erb +0 -1
- data/merb_default_generators/resource_controller/templates/helper.rb +0 -5
- data/merb_default_generators/resource_controller/templates/index.html.erb +0 -1
- data/merb_default_generators/resource_controller/templates/new.html.erb +0 -1
- data/merb_default_generators/resource_controller/templates/show.html.erb +0 -1
- data/merb_generators/controller/USAGE +0 -5
- data/merb_generators/controller/controller_generator.rb +0 -16
- data/merb_generators/controller/templates/controller.rb +0 -8
- data/merb_generators/controller/templates/helper.rb +0 -5
- data/merb_generators/controller/templates/index.html.erb +0 -3
- data/merb_generators/part_controller/USAGE +0 -5
- data/merb_generators/part_controller/part_controller_generator.rb +0 -27
- data/merb_generators/part_controller/templates/controller.rb +0 -8
- data/merb_generators/part_controller/templates/helper.rb +0 -5
- data/merb_generators/part_controller/templates/index.html.erb +0 -3
- data/merb_generators/resource/USAGE +0 -0
- data/merb_generators/resource/resource_generator.rb +0 -67
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +0 -67
- data/rspec_generators/merb_controller_test/templates/controller_spec.rb +0 -8
- data/rspec_generators/merb_controller_test/templates/edit_spec.rb +0 -12
- data/rspec_generators/merb_controller_test/templates/helper_spec.rb +0 -5
- data/rspec_generators/merb_controller_test/templates/index_spec.rb +0 -12
- data/rspec_generators/merb_controller_test/templates/new_spec.rb +0 -12
- data/rspec_generators/merb_controller_test/templates/show_spec.rb +0 -5
- data/rspec_generators/merb_model_test/merb_model_test_generator.rb +0 -26
- data/rspec_generators/merb_model_test/templates/model_spec_template.erb +0 -7
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/spec/fixtures/config/environments/environment_config_test.yml +0 -1
- data/spec/fixtures/config/merb.yml +0 -18
- data/spec/fixtures/controllers/dispatch_spec_controllers.rb +0 -235
- data/spec/fixtures/controllers/render_spec_controllers.rb +0 -184
- data/spec/fixtures/foo.rb +0 -3
- data/spec/fixtures/mailers/views/layout/application.html.erb +0 -3
- data/spec/fixtures/mailers/views/layout/application.text.erb +0 -3
- data/spec/fixtures/mailers/views/test_mail_controller/eighth.html.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/eighth.text.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/first.html.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/first.text.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/ninth.html.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/ninth.text.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/second.text.erb +0 -1
- data/spec/fixtures/mailers/views/test_mail_controller/third.html.erb +0 -1
- data/spec/fixtures/models/router_spec_models.rb +0 -30
- data/spec/fixtures/parts/views/layout/todo_part.html.erb +0 -3
- data/spec/fixtures/parts/views/layout/todo_part.xml.erb +0 -3
- data/spec/fixtures/parts/views/todo_part/formatted_output.html.erb +0 -1
- data/spec/fixtures/parts/views/todo_part/formatted_output.js.erb +0 -1
- data/spec/fixtures/parts/views/todo_part/formatted_output.xml.erb +0 -1
- data/spec/fixtures/parts/views/todo_part/list.html.erb +0 -3
- data/spec/fixtures/sample.txt +0 -1
- data/spec/fixtures/views/erubis.html.erb +0 -1
- data/spec/fixtures/views/examples/_erubis.html.erb +0 -1
- data/spec/fixtures/views/examples/_haml.html.haml +0 -1
- data/spec/fixtures/views/examples/_markaby.html.mab +0 -1
- data/spec/fixtures/views/examples/_throw_content.html.erb +0 -6
- data/spec/fixtures/views/examples/hello.xml.builder +0 -1
- data/spec/fixtures/views/examples/js.js.erb +0 -1
- data/spec/fixtures/views/examples/template_catch_content.html.erb +0 -15
- data/spec/fixtures/views/examples/template_catch_content_from_partial.html.erb +0 -6
- data/spec/fixtures/views/examples/template_throw_content.html.erb +0 -10
- data/spec/fixtures/views/examples/template_throw_content_without_block.html.erb +0 -3
- data/spec/fixtures/views/exceptions/admin_access_required.html.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/_nested_js.js.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/_nested_xml.xml.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/_render_partial_multiple_times.html.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/erubis_templates.html.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/erubis_templates.js.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/erubis_templates.rhtml +0 -1
- data/spec/fixtures/views/extension_template_controller/erubis_templates.xml.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/haml_index.html.haml +0 -0
- data/spec/fixtures/views/extension_template_controller/haml_templates.html.haml +0 -1
- data/spec/fixtures/views/extension_template_controller/haml_templates.js.haml +0 -1
- data/spec/fixtures/views/extension_template_controller/haml_templates.xml.haml +0 -1
- data/spec/fixtures/views/extension_template_controller/index.html.erb +0 -0
- data/spec/fixtures/views/extension_template_controller/markaby_index.html.mab +0 -0
- data/spec/fixtures/views/extension_template_controller/markaby_templates.html.mab +0 -1
- data/spec/fixtures/views/extension_template_controller/markaby_templates.js.mab +0 -1
- data/spec/fixtures/views/extension_template_controller/markaby_templates.xml.mab +0 -1
- data/spec/fixtures/views/extension_template_controller/render_multiple_partials.html.erb +0 -4
- data/spec/fixtures/views/extension_template_controller/render_nested_js.js.erb +0 -1
- data/spec/fixtures/views/extension_template_controller/render_nested_xml.xml.erb +0 -1
- data/spec/fixtures/views/haml.html.haml +0 -1
- data/spec/fixtures/views/haml.xml.haml +0 -2
- data/spec/fixtures/views/layout/application.html.erb +0 -1
- data/spec/fixtures/views/layout/application.xml.erb +0 -1
- data/spec/fixtures/views/layout/nested/example.html.erb +0 -1
- data/spec/fixtures/views/markaby.html.mab +0 -1
- data/spec/fixtures/views/nested/example/test.html.erb +0 -1
- data/spec/fixtures/views/partials/_erubis.html.erb +0 -1
- data/spec/fixtures/views/partials/_erubis_collection.html.erb +0 -1
- data/spec/fixtures/views/partials/_erubis_collection_with_locals.html.erb +0 -1
- data/spec/fixtures/views/partials/_erubis_new.html.erb +0 -1
- data/spec/fixtures/views/partials/_haml.html.haml +0 -1
- data/spec/fixtures/views/partials/_haml_collection.html.haml +0 -1
- data/spec/fixtures/views/partials/_haml_collection_with_locals.html.haml +0 -1
- data/spec/fixtures/views/partials/_haml_new.html.haml +0 -1
- data/spec/fixtures/views/partials/_markaby.html.mab +0 -1
- data/spec/fixtures/views/partials/_markaby_collection.html.mab +0 -1
- data/spec/fixtures/views/partials/_markaby_collection_with_locals.html.mab +0 -1
- data/spec/fixtures/views/partials/_markaby_new.html.mab +0 -1
- data/spec/fixtures/views/render_object_controller/render_object_with_template.html.erb +0 -1
- data/spec/fixtures/views/render_object_controller/render_object_with_template.js.erb +0 -1
- data/spec/fixtures/views/render_object_controller/render_object_with_template.xml.erb +0 -1
- data/spec/fixtures/views/template_views/interface__buffer_erubis.html.erb +0 -4
- data/spec/fixtures/views/template_views/interface__buffer_haml.html.haml +0 -7
- data/spec/fixtures/views/template_views/interface__buffer_markaby.html.mab +0 -7
- data/spec/fixtures/views/template_views/interface_capture_erubis.html.erb +0 -15
- data/spec/fixtures/views/template_views/interface_capture_haml.html.haml +0 -15
- data/spec/fixtures/views/template_views/interface_capture_markaby.html.mab +0 -4
- data/spec/fixtures/views/template_views/interface_concat_erubis.html.erb +0 -12
- data/spec/fixtures/views/template_views/interface_concat_haml.html.haml +0 -11
- data/spec/fixtures/views/template_views/interface_concat_markaby.html.mab +0 -14
- data/spec/fixtures/views/test.dir/the_template.html.erb +0 -1
- data/spec/merb/abstract_controller_spec.rb +0 -38
- data/spec/merb/assets_spec.rb +0 -207
- data/spec/merb/caching_spec.rb +0 -102
- data/spec/merb/config_spec.rb +0 -29
- data/spec/merb/controller_filters_spec.rb +0 -253
- data/spec/merb/controller_spec.rb +0 -126
- data/spec/merb/cookie_store_spec.rb +0 -72
- data/spec/merb/cookies_spec.rb +0 -96
- data/spec/merb/core_ext/class_spec.rb +0 -97
- data/spec/merb/core_ext/enumerable_spec.rb +0 -27
- data/spec/merb/core_ext/hash_spec.rb +0 -251
- data/spec/merb/core_ext/inflector_spec.rb +0 -34
- data/spec/merb/core_ext/kernel_spec.rb +0 -25
- data/spec/merb/core_ext/numeric_spec.rb +0 -26
- data/spec/merb/core_ext/object_spec.rb +0 -47
- data/spec/merb/core_ext/string_spec.rb +0 -22
- data/spec/merb/core_ext/symbol_spec.rb +0 -7
- data/spec/merb/dependency_spec.rb +0 -22
- data/spec/merb/dispatch_spec.rb +0 -528
- data/spec/merb/fake_request_spec.rb +0 -80
- data/spec/merb/generator_spec.rb +0 -248
- data/spec/merb/handler_spec.rb +0 -169
- data/spec/merb/mail_controller_spec.rb +0 -177
- data/spec/merb/mailer_spec.rb +0 -87
- data/spec/merb/multipart_spec.rb +0 -50
- data/spec/merb/part_controller_spec.rb +0 -124
- data/spec/merb/plugins_spec.rb +0 -80
- data/spec/merb/render_spec.rb +0 -469
- data/spec/merb/request_spec.rb +0 -287
- data/spec/merb/responder_spec.rb +0 -562
- data/spec/merb/router_spec.rb +0 -900
- data/spec/merb/server_spec.rb +0 -19
- data/spec/merb/template_spec.rb +0 -41
- data/spec/merb/upload_handler_spec.rb +0 -108
- data/spec/merb/version_spec.rb +0 -33
- data/spec/merb/view_context_spec.rb +0 -366
- data/spec/spec_generator_helper.rb +0 -34
- data/spec/spec_helper.rb +0 -101
- data/spec/spec_helpers/url_shared_behaviour.rb +0 -112
- data/test_unit_generators/merb_controller_test/merb_controller_test_generator.rb +0 -53
- data/test_unit_generators/merb_controller_test/templates/functional_test.rb +0 -17
- data/test_unit_generators/merb_controller_test/templates/helper_test.rb +0 -9
- data/test_unit_generators/merb_model_test/merb_model_test_generator.rb +0 -29
- data/test_unit_generators/merb_model_test/templates/model_test_unit_template.erb +0 -9
@@ -1,449 +0,0 @@
|
|
1
|
-
require 'enumerator'
|
2
|
-
|
3
|
-
module Merb
|
4
|
-
class << self
|
5
|
-
# Provides the currently implemented mime types as a hash
|
6
|
-
def available_mime_types
|
7
|
-
ResponderMixin::Rest::TYPES
|
8
|
-
end
|
9
|
-
|
10
|
-
# Any specific outgoing headers should be included here. These are not
|
11
|
-
# the content-type header but anything in addition to it.
|
12
|
-
# +tranform_method+ should be set to a symbol of the method used to
|
13
|
-
# transform a resource into this mime type.
|
14
|
-
# For example for the :xml mime type an object might be transformed by
|
15
|
-
# calling :to_xml, or for the :js mime type, :to_json.
|
16
|
-
# If there is no transform method, use nil.
|
17
|
-
def add_mime_type(key,transform_method, values,new_response_headers = {})
|
18
|
-
raise ArgumentError unless key.is_a?(Symbol) && values.is_a?(Array)
|
19
|
-
ResponderMixin::Rest::TYPES.update(key => values)
|
20
|
-
add_response_headers!(key, new_response_headers)
|
21
|
-
ResponderMixin::Rest::TRANSFORM_METHODS.merge!(key => transform_method)
|
22
|
-
end
|
23
|
-
|
24
|
-
def remove_mime_type(key)
|
25
|
-
key == :all ? false : ResponderMixin::Rest::TYPES.delete(key)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Return the method name (if any) for the mimetype
|
29
|
-
def mime_transform_method(key)
|
30
|
-
ResponderMixin::Rest::TRANSFORM_METHODS[key]
|
31
|
-
end
|
32
|
-
|
33
|
-
# Return default arguments for transform method (if any)
|
34
|
-
def mime_transform_method_defaults(key)
|
35
|
-
ResponderMixin::Rest::TRANSFORM_METHOD_DEFAULTS[key]
|
36
|
-
end
|
37
|
-
|
38
|
-
# Set default arguments/proc for a format transform method
|
39
|
-
def set_mime_transform_method_defaults(key, *args, &block)
|
40
|
-
raise "Unknown mimetype #{key}" unless ResponderMixin::Rest::TRANSFORM_METHODS[key]
|
41
|
-
args = block if block_given?
|
42
|
-
ResponderMixin::Rest::TRANSFORM_METHOD_DEFAULTS[key] = args unless args.empty?
|
43
|
-
end
|
44
|
-
|
45
|
-
# Adds outgoing headers to a mime type. This can be done with the Merb.add_mime_type method
|
46
|
-
# or directly here.
|
47
|
-
# ===Example
|
48
|
-
# {{[
|
49
|
-
# Merb.outgoing_headers!(:xml => { :Encoding => "UTF-8" })
|
50
|
-
# ]}}
|
51
|
-
#
|
52
|
-
# This method is destructive on any already defined outgoing headers
|
53
|
-
def add_response_headers!(key, values = {})
|
54
|
-
raise ArgumentError unless key.is_a?(Symbol) && values.is_a?(Hash)
|
55
|
-
response_headers[key] = values
|
56
|
-
end
|
57
|
-
|
58
|
-
def response_headers
|
59
|
-
ResponderMixin::Rest::RESPONSE_HEADERS
|
60
|
-
end
|
61
|
-
|
62
|
-
# Completely removes any headers set that are additional to the content-type header.
|
63
|
-
def remove_response_headers!(key)
|
64
|
-
raise ArgumentError unless key.is_a?(Symbol)
|
65
|
-
response_headers[key] = {}
|
66
|
-
end
|
67
|
-
|
68
|
-
# Sets the mime types and outgoing headers to their original states
|
69
|
-
def reset_default_mime_types!
|
70
|
-
available_mime_types.clear
|
71
|
-
response_headers.clear
|
72
|
-
Merb.add_mime_type(:all,nil,%w[*/*])
|
73
|
-
Merb.add_mime_type(:yaml,:to_yaml,%w[application/x-yaml text/yaml])
|
74
|
-
Merb.add_mime_type(:text,:to_text,%w[text/plain])
|
75
|
-
Merb.add_mime_type(:html,nil,%w[text/html application/xhtml+xml application/html])
|
76
|
-
Merb.add_mime_type(:xml,:to_xml,%w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
|
77
|
-
Merb.add_mime_type(:js,:to_json,%w[ text/javascript application/javascript application/x-javascript])
|
78
|
-
Merb.add_mime_type(:json,:to_json,%w[application/json text/x-json ])
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
# The ResponderMixin adds methods that help you manage what
|
84
|
-
# formats your controllers have available, determine what format(s)
|
85
|
-
# the client requested and is capable of handling, and perform
|
86
|
-
# content negotiation to pick the proper content format to
|
87
|
-
# deliver.
|
88
|
-
#
|
89
|
-
# If you hear someone say "Use provides" they're talking about the
|
90
|
-
# Responder. If you hear someone ask "What happened to respond_to?"
|
91
|
-
# it was replaced by provides and the other Responder methods.
|
92
|
-
#
|
93
|
-
# == A simple example
|
94
|
-
#
|
95
|
-
# The best way to understand how all of these pieces fit together is
|
96
|
-
# with an example. Here's a simple web-service ready resource that
|
97
|
-
# provides a list of all the widgets we know about. The widget list is
|
98
|
-
# available in 3 formats: :html (the default), plus :xml and :text.
|
99
|
-
#
|
100
|
-
# class Widgets < Application
|
101
|
-
# provides :html # This is the default, but you can
|
102
|
-
# # be explicit if you like.
|
103
|
-
# provides :xml, :text
|
104
|
-
#
|
105
|
-
# def index
|
106
|
-
# @widgets = Widget.fetch
|
107
|
-
# render @widgets
|
108
|
-
# end
|
109
|
-
# end
|
110
|
-
#
|
111
|
-
# Let's look at some example requests for this list of widgets. We'll
|
112
|
-
# assume they're all GET requests, but that's only to make the examples
|
113
|
-
# easier; this works for the full set of RESTful methods.
|
114
|
-
#
|
115
|
-
# 1. The simplest case, /widgets.html
|
116
|
-
# Since the request includes a specific format (.html) we know
|
117
|
-
# what format to return. Since :html is in our list of provided
|
118
|
-
# formats, that's what we'll return. +render+ will look
|
119
|
-
# for an index.html.erb (or another template format
|
120
|
-
# like index.html.mab; see the documentation on Template engines)
|
121
|
-
#
|
122
|
-
# 2. Almost as simple, /widgets.xml
|
123
|
-
# This is very similar. They want :xml, we have :xml, so
|
124
|
-
# that's what they get. If +render+ doesn't find an
|
125
|
-
# index.xml.builder or similar template, it will call +to_xml+
|
126
|
-
# on @widgets. This may or may not do something useful, but you can
|
127
|
-
# see how it works.
|
128
|
-
#
|
129
|
-
# 3. A browser request for /widgets
|
130
|
-
# This time the URL doesn't say what format is being requested, so
|
131
|
-
# we'll look to the HTTP Accept: header. If it's '*/*' (anything),
|
132
|
-
# we'll use the first format on our list, :html by default.
|
133
|
-
#
|
134
|
-
# If it parses to a list of accepted formats, we'll look through
|
135
|
-
# them, in order, until we find one we have available. If we find
|
136
|
-
# one, we'll use that. Otherwise, we can't fulfill the request:
|
137
|
-
# they asked for a format we don't have. So we raise
|
138
|
-
# 406: Not Acceptable.
|
139
|
-
#
|
140
|
-
# == A more complex example
|
141
|
-
#
|
142
|
-
# Sometimes you don't have the same code to handle each available
|
143
|
-
# format. Sometimes you need to load different data to serve
|
144
|
-
# /widgets.xml versus /widgets.txt. In that case, you can use
|
145
|
-
# +content_type+ to determine what format will be delivered.
|
146
|
-
#
|
147
|
-
# class Widgets < Application
|
148
|
-
# def action1
|
149
|
-
# if content_type == :text
|
150
|
-
# Widget.load_text_formatted(params[:id])
|
151
|
-
# else
|
152
|
-
# render
|
153
|
-
# end
|
154
|
-
# end
|
155
|
-
#
|
156
|
-
# def action2
|
157
|
-
# case content_type
|
158
|
-
# when :html
|
159
|
-
# handle_html()
|
160
|
-
# when :xml
|
161
|
-
# handle_xml()
|
162
|
-
# when :text
|
163
|
-
# handle_text()
|
164
|
-
# else
|
165
|
-
# render
|
166
|
-
# end
|
167
|
-
# end
|
168
|
-
# end
|
169
|
-
#
|
170
|
-
# You can do any standard Ruby flow control using +content_type+. If
|
171
|
-
# you don't call it yourself, it will be called (triggering content
|
172
|
-
# negotiation) by +render+.
|
173
|
-
#
|
174
|
-
# Once +content_type+ has been called, the output format is frozen,
|
175
|
-
# and none of the provides methods can be used.
|
176
|
-
module ResponderMixin
|
177
|
-
|
178
|
-
def self.included(base) # :nodoc:
|
179
|
-
base.extend(ClassMethods)
|
180
|
-
base.class_eval do
|
181
|
-
class_inheritable_accessor :class_provided_formats
|
182
|
-
class_inheritable_accessor :class_provided_format_arguments
|
183
|
-
end
|
184
|
-
base.reset_provides
|
185
|
-
end
|
186
|
-
|
187
|
-
module ClassMethods
|
188
|
-
|
189
|
-
# Adds symbols representing formats to the controller's
|
190
|
-
# default list of provided_formats. These will apply to
|
191
|
-
# every action in the controller, unless modified in the action.
|
192
|
-
# If the last argument is a Hash or an Array, these are regarded
|
193
|
-
# as arguments to pass to the to_<mime_type> method as needed.
|
194
|
-
def provides(*formats, &block)
|
195
|
-
options = extract_provides_options(formats, &block)
|
196
|
-
formats.each do |fmt|
|
197
|
-
self.class_provided_formats << fmt unless class_provided_formats.include?(fmt)
|
198
|
-
self.class_provided_format_arguments[fmt] = options unless options.nil?
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# Overwrites the controller's list of provided_formats. These
|
203
|
-
# will apply to every action in the controller, unless modified
|
204
|
-
# in the action.
|
205
|
-
def only_provides(*formats)
|
206
|
-
clear_provides
|
207
|
-
provides(*formats)
|
208
|
-
end
|
209
|
-
|
210
|
-
# Removes formats from the controller's
|
211
|
-
# default list of provided_formats. These will apply to
|
212
|
-
# every action in the controller, unless modified in the action.
|
213
|
-
def does_not_provide(*formats)
|
214
|
-
self.class_provided_formats -= formats
|
215
|
-
formats.each { |fmt| self.class_provided_format_arguments.delete(fmt) }
|
216
|
-
end
|
217
|
-
|
218
|
-
# Clear any formats and their options
|
219
|
-
def clear_provides
|
220
|
-
self.class_provided_formats = []
|
221
|
-
self.class_provided_format_arguments = {}
|
222
|
-
end
|
223
|
-
|
224
|
-
# Reset to the default list of formats
|
225
|
-
def reset_provides
|
226
|
-
only_provides(:html)
|
227
|
-
end
|
228
|
-
|
229
|
-
# Extract arguments for provided format methods
|
230
|
-
def extract_provides_options(args, &block)
|
231
|
-
return block if block_given?
|
232
|
-
case args.last
|
233
|
-
when Hash then [args.pop]
|
234
|
-
when Array then args.pop
|
235
|
-
when Proc then args.pop
|
236
|
-
else nil
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
end
|
241
|
-
|
242
|
-
# Returns the current list of formats provided for this instance
|
243
|
-
# of the controller. It starts with what has been set in the controller
|
244
|
-
# (or :html by default) but can be modifed on a per-action basis.
|
245
|
-
def provided_formats
|
246
|
-
@_provided_formats ||= class_provided_formats.dup
|
247
|
-
end
|
248
|
-
|
249
|
-
# Sets the provided formats for this action. Usually, you would
|
250
|
-
# use a combination of +provides+, +only_provides+ and +does_not_provide+
|
251
|
-
# to manage this, but you can set it directly.
|
252
|
-
# If the last argument is a Hash or an Array, these are regarded
|
253
|
-
# as arguments to pass to the to_<mime_type> method as needed.
|
254
|
-
def set_provided_formats(*formats, &block)
|
255
|
-
raise_if_content_type_already_set!
|
256
|
-
@_provided_formats = []
|
257
|
-
@_provided_format_arguments = {}
|
258
|
-
provides(*formats.flatten, &block)
|
259
|
-
end
|
260
|
-
alias :provided_formats= :set_provided_formats
|
261
|
-
|
262
|
-
# Returns a Hash of arguments for format methods
|
263
|
-
def provided_format_arguments
|
264
|
-
@_provided_format_arguments ||= Hash.new.replace(class_provided_format_arguments)
|
265
|
-
end
|
266
|
-
|
267
|
-
# Returns the arguments (if any) for the mime_transform_method call
|
268
|
-
def provided_format_arguments_for(fmt)
|
269
|
-
self.provided_format_arguments[fmt] || Merb.mime_transform_method_defaults(fmt)
|
270
|
-
end
|
271
|
-
|
272
|
-
# Adds formats to the list of provided formats for this particular
|
273
|
-
# request. Usually used to add formats to a single action. See also
|
274
|
-
# the controller-level provides that affects all actions in a controller.
|
275
|
-
def provides(*formats, &block)
|
276
|
-
raise_if_content_type_already_set!
|
277
|
-
options = self.class.extract_provides_options(formats, &block)
|
278
|
-
formats.each do |fmt|
|
279
|
-
self.provided_formats << fmt unless provided_formats.include?(fmt)
|
280
|
-
self.provided_format_arguments[fmt] = options unless options.nil?
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
# Sets list of provided formats for this particular
|
285
|
-
# request. Usually used to limit formats to a single action. See also
|
286
|
-
# the controller-level provides that affects all actions in a controller.
|
287
|
-
def only_provides(*formats)
|
288
|
-
self.set_provided_formats(*formats)
|
289
|
-
end
|
290
|
-
|
291
|
-
# Removes formats from the list of provided formats for this particular
|
292
|
-
# request. Usually used to remove formats from a single action. See
|
293
|
-
# also the controller-level provides that affects all actions in a
|
294
|
-
# controller.
|
295
|
-
def does_not_provide(*formats)
|
296
|
-
formats.flatten!
|
297
|
-
self.provided_formats -= formats
|
298
|
-
formats.each { |fmt| self.provided_format_arguments.delete(fmt) }
|
299
|
-
end
|
300
|
-
|
301
|
-
# Do the content negotiation:
|
302
|
-
# 1. if params[:format] is there, and provided, use it
|
303
|
-
# 2. Parse the Accept header
|
304
|
-
# 3. If it's */*, use the first provided format
|
305
|
-
# 4. Look for one that is provided, in order of request
|
306
|
-
# 5. Raise 406 if none found
|
307
|
-
def perform_content_negotiation # :nodoc:
|
308
|
-
raise Merb::ControllerExceptions::NotAcceptable if provided_formats.empty?
|
309
|
-
if fmt = params[:format]
|
310
|
-
if provided_formats.include?(fmt.to_sym)
|
311
|
-
fmt.to_sym
|
312
|
-
else
|
313
|
-
raise Merb::ControllerExceptions::NotAcceptable
|
314
|
-
end
|
315
|
-
else
|
316
|
-
accepts = Rest::Responder.parse(request.accept).
|
317
|
-
collect {|t| t.to_sym}
|
318
|
-
if accepts.include?(:all)
|
319
|
-
provided_formats.first
|
320
|
-
else
|
321
|
-
accepts.each do |type|
|
322
|
-
return type if provided_formats.include?(type)
|
323
|
-
end
|
324
|
-
raise Merb::ControllerExceptions::NotAcceptable
|
325
|
-
end
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
# Checks to see if content negotiation has already been performed.
|
330
|
-
# If it has, you can no longer modify the list of provided formats.
|
331
|
-
def content_type_set?
|
332
|
-
!@_content_type.nil?
|
333
|
-
end
|
334
|
-
|
335
|
-
# Returns the output format for this request, based on the
|
336
|
-
# provided formats, <tt>params[:format]</tt> and the client's HTTP
|
337
|
-
# Accept header.
|
338
|
-
#
|
339
|
-
# The first time this is called, it triggers content negotiation
|
340
|
-
# and caches the value. Once you call +content_type+ you can
|
341
|
-
# not set or change the list of provided formats.
|
342
|
-
#
|
343
|
-
# Called automatically by +render+, so you should only call it if
|
344
|
-
# you need the value, not to trigger content negotiation.
|
345
|
-
def content_type
|
346
|
-
unless content_type_set?
|
347
|
-
@_content_type = perform_content_negotiation
|
348
|
-
raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{@_content_type}") unless
|
349
|
-
Merb.available_mime_types.has_key?(@_content_type)
|
350
|
-
headers['Content-Type'] = Merb.available_mime_types[@_content_type].first
|
351
|
-
end
|
352
|
-
@_content_type
|
353
|
-
end
|
354
|
-
|
355
|
-
# Sets the output content_type for this request. Normally you
|
356
|
-
# should use +provides+, +does_not_provide+ and +only_provides+
|
357
|
-
# and then let the content negotiation process determine the proper
|
358
|
-
# content_type. However, in some circumstances you may want to
|
359
|
-
# set it directly, or override what content negotiation picks.
|
360
|
-
def content_type=(new_type)
|
361
|
-
@_content_type = new_type
|
362
|
-
end
|
363
|
-
|
364
|
-
private
|
365
|
-
|
366
|
-
def raise_if_content_type_already_set!
|
367
|
-
raise "Cannot modify provided_formats because content_type has already been set" if content_type_set?
|
368
|
-
end
|
369
|
-
|
370
|
-
module Rest
|
371
|
-
|
372
|
-
TYPES = {}
|
373
|
-
RESPONSE_HEADERS = Hash.new([])
|
374
|
-
TRANSFORM_METHODS = {}
|
375
|
-
TRANSFORM_METHOD_DEFAULTS = {}
|
376
|
-
|
377
|
-
class Responder
|
378
|
-
|
379
|
-
protected
|
380
|
-
|
381
|
-
def self.parse(accept_header)
|
382
|
-
# parse the raw accept header into a unique, sorted array of AcceptType objects
|
383
|
-
list = accept_header.to_s.split(/,/).enum_for(:each_with_index).map do |entry,index|
|
384
|
-
AcceptType.new(entry,index += 1)
|
385
|
-
end.sort.uniq
|
386
|
-
# firefox (and possibly other browsers) send broken default accept headers.
|
387
|
-
# fix them up by sorting alternate xml forms (namely application/xhtml+xml)
|
388
|
-
# ahead of pure xml types (application/xml,text/xml).
|
389
|
-
if app_xml = list.detect{|e| e.super_range == 'application/xml'}
|
390
|
-
list.select{|e| e.to_s =~ /\+xml/}.each { |acc_type|
|
391
|
-
list[list.index(acc_type)],list[list.index(app_xml)] =
|
392
|
-
list[list.index(app_xml)],list[list.index(acc_type)] }
|
393
|
-
end
|
394
|
-
list
|
395
|
-
end
|
396
|
-
|
397
|
-
end
|
398
|
-
|
399
|
-
class AcceptType
|
400
|
-
|
401
|
-
attr_reader :media_range, :quality, :index, :type, :sub_type
|
402
|
-
|
403
|
-
def initialize(entry,index)
|
404
|
-
@index = index
|
405
|
-
@media_range, quality = entry.split(/;\s*q=/).map{|a| a.strip }
|
406
|
-
@type, @sub_type = @media_range.split(/\//)
|
407
|
-
quality ||= 0.0 if @media_range == '*/*'
|
408
|
-
@quality = ((quality || 1.0).to_f * 100).to_i
|
409
|
-
end
|
410
|
-
|
411
|
-
def <=>(entry)
|
412
|
-
c = entry.quality <=> quality
|
413
|
-
c = index <=> entry.index if c == 0
|
414
|
-
c
|
415
|
-
end
|
416
|
-
|
417
|
-
def eql?(entry)
|
418
|
-
synonyms.include?(entry.media_range)
|
419
|
-
end
|
420
|
-
|
421
|
-
def ==(entry); eql?(entry); end
|
422
|
-
|
423
|
-
def hash; super_range.hash; end
|
424
|
-
|
425
|
-
def synonyms
|
426
|
-
@syns ||= TYPES.values.select{|e| e.include?(@media_range)}.flatten
|
427
|
-
end
|
428
|
-
|
429
|
-
def super_range
|
430
|
-
synonyms.first || @media_range
|
431
|
-
end
|
432
|
-
|
433
|
-
def to_sym
|
434
|
-
TYPES.select{|k,v|
|
435
|
-
v == synonyms || v[0] == synonyms[0]}.flatten.first
|
436
|
-
end
|
437
|
-
|
438
|
-
def to_s
|
439
|
-
@media_range
|
440
|
-
end
|
441
|
-
|
442
|
-
end
|
443
|
-
|
444
|
-
end
|
445
|
-
|
446
|
-
end
|
447
|
-
reset_default_mime_types!
|
448
|
-
|
449
|
-
end
|
@@ -1,558 +0,0 @@
|
|
1
|
-
module Merb
|
2
|
-
# The ViewContextMixin module provides a number of helper methods to views for
|
3
|
-
# linking to assets and other pages, dealing with JavaScript, and caching.
|
4
|
-
module ViewContextMixin
|
5
|
-
|
6
|
-
include Merb::Assets::AssetHelpers
|
7
|
-
|
8
|
-
# :section: Accessing Assets
|
9
|
-
# Merb provides views with convenience methods for links images and other assets.
|
10
|
-
|
11
|
-
# Creates a link for the URL given in +url+ with the text in +name+; HTML options are given in the +opts+
|
12
|
-
# hash.
|
13
|
-
#
|
14
|
-
# ==== Options
|
15
|
-
# The +opts+ hash is used to set HTML attributes on the tag.
|
16
|
-
#
|
17
|
-
# ==== Examples
|
18
|
-
# link_to("The Merb home page", "http://www.merbivore.com/")
|
19
|
-
# # => <a href="http://www.merbivore.com/">The Merb home page</a>
|
20
|
-
#
|
21
|
-
# link_to("The Ruby home page", "http://www.ruby-lang.org", {'class' => 'special', 'target' => 'blank'})
|
22
|
-
# # => <a href="http://www.ruby-lang.org" class="special" target="blank">The Ruby home page</a>
|
23
|
-
#
|
24
|
-
# link_to p.title, "/blog/show/#{p.id}"
|
25
|
-
# # => <a href="blog/show/13">The Entry Title</a>
|
26
|
-
#
|
27
|
-
def link_to(name, url='', opts={})
|
28
|
-
opts[:href] ||= url
|
29
|
-
%{<a #{ opts.to_xml_attributes }>#{name}</a>}
|
30
|
-
end
|
31
|
-
|
32
|
-
# Creates an image tag with the +src+ attribute set to the +img+ argument. The path
|
33
|
-
# prefix defaults to <tt>/images/</tt>. The path prefix can be overriden by setting a +:path+
|
34
|
-
# parameter in the +opts+ hash. The rest of the +opts+ hash sets HTML attributes.
|
35
|
-
#
|
36
|
-
# ==== Options
|
37
|
-
# path:: Sets the path prefix for the image (defaults to +/images/+)
|
38
|
-
#
|
39
|
-
# All other options in +opts+ set HTML attributes on the tag.
|
40
|
-
#
|
41
|
-
# ==== Examples
|
42
|
-
# image_tag('foo.gif')
|
43
|
-
# # => <img src='/images/foo.gif' />
|
44
|
-
#
|
45
|
-
# image_tag('foo.gif', :class => 'bar')
|
46
|
-
# # => <img src='/images/foo.gif' class='bar' />
|
47
|
-
#
|
48
|
-
# image_tag('foo.gif', :path => '/files/')
|
49
|
-
# # => <img src='/files/foo.gif' />
|
50
|
-
#
|
51
|
-
# image_tag('http://test.com/foo.gif')
|
52
|
-
# # => <img src="http://test.com/foo.gif">
|
53
|
-
def image_tag(img, opts={})
|
54
|
-
opts[:path] ||=
|
55
|
-
if img =~ %r{^https?://}
|
56
|
-
''
|
57
|
-
else
|
58
|
-
if Merb::Config[:path_prefix]
|
59
|
-
Merb::Config[:path_prefix] + '/images/'
|
60
|
-
else
|
61
|
-
'/images/'
|
62
|
-
end
|
63
|
-
end
|
64
|
-
opts[:src] ||= opts.delete(:path) + img
|
65
|
-
%{<img #{ opts.to_xml_attributes } />}
|
66
|
-
end
|
67
|
-
|
68
|
-
# :section: JavaScript related functions
|
69
|
-
#
|
70
|
-
|
71
|
-
# Escapes text for use in JavaScript, replacing unsafe strings with their
|
72
|
-
# escaped equivalent.
|
73
|
-
#
|
74
|
-
# ==== Examples
|
75
|
-
# escape_js("'Lorem ipsum!' -- Some guy")
|
76
|
-
# # => "\\'Lorem ipsum!\\' -- Some guy"
|
77
|
-
#
|
78
|
-
# escape_js("Please keep text\nlines as skinny\nas possible.")
|
79
|
-
# # => "Please keep text\\nlines as skinny\\nas possible."
|
80
|
-
def escape_js(javascript)
|
81
|
-
(javascript || '').gsub('\\','\0\0').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }
|
82
|
-
end
|
83
|
-
|
84
|
-
# Creates a link tag with the text in +name+ and the <tt>onClick</tt> handler set to a JavaScript
|
85
|
-
# string in +function+.
|
86
|
-
#
|
87
|
-
# ==== Examples
|
88
|
-
# link_to_function('Click me', "alert('hi!')")
|
89
|
-
# # => <a href="#" onclick="alert('hi!'); return false;">Click me</a>
|
90
|
-
#
|
91
|
-
# link_to_function('Add to cart', "item_total += 1; alert('Item added!');")
|
92
|
-
# # => <a href="#" onclick="item_total += 1; alert('Item added!'); return false;">Add to cart</a>
|
93
|
-
#
|
94
|
-
def link_to_function(name, function)
|
95
|
-
%{<a href="#" onclick="#{function}; return false;">#{name}</a>}
|
96
|
-
end
|
97
|
-
|
98
|
-
# The js method simply calls +to_json+ on an object in +data+; if the object
|
99
|
-
# does not implement a +to_json+ method, then it calls +to_json+ on
|
100
|
-
# +data.inspect+.
|
101
|
-
#
|
102
|
-
# ==== Examples
|
103
|
-
# js({'user' => 'Lewis', 'page' => 'home'})
|
104
|
-
# # => "{\"user\":\"Lewis\",\"page\":\"home\"}"
|
105
|
-
#
|
106
|
-
# my_array = [1, 2, {"a"=>3.141}, false, true, nil, 4..10]
|
107
|
-
# js(my_array)
|
108
|
-
# # => "[1,2,{\"a\":3.141},false,true,null,\"4..10\"]"
|
109
|
-
#
|
110
|
-
def js(data)
|
111
|
-
if data.respond_to? :to_json
|
112
|
-
data.to_json
|
113
|
-
else
|
114
|
-
data.inspect.to_json
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# :section: External JavaScript and Stylesheets
|
119
|
-
#
|
120
|
-
# You can use require_js(:prototype) or require_css(:shinystyles)
|
121
|
-
# from any view or layout, and the scripts will only be included once
|
122
|
-
# in the head of the final page. To get this effect, the head of your layout you will
|
123
|
-
# need to include a call to include_required_js and include_required_css.
|
124
|
-
#
|
125
|
-
# ==== Examples
|
126
|
-
# # File: app/views/layouts/application.html.erb
|
127
|
-
#
|
128
|
-
# <html>
|
129
|
-
# <head>
|
130
|
-
# <%= include_required_js %>
|
131
|
-
# <%= include_required_css %>
|
132
|
-
# </head>
|
133
|
-
# <body>
|
134
|
-
# <%= catch_content :layout %>
|
135
|
-
# </body>
|
136
|
-
# </html>
|
137
|
-
#
|
138
|
-
# # File: app/views/whatever/_part1.herb
|
139
|
-
#
|
140
|
-
# <% require_js 'this' -%>
|
141
|
-
# <% require_css 'that', 'another_one' -%>
|
142
|
-
#
|
143
|
-
# # File: app/views/whatever/_part2.herb
|
144
|
-
#
|
145
|
-
# <% require_js 'this', 'something_else' -%>
|
146
|
-
# <% require_css 'that' -%>
|
147
|
-
#
|
148
|
-
# # File: app/views/whatever/index.herb
|
149
|
-
#
|
150
|
-
# <%= partial(:part1) %>
|
151
|
-
# <%= partial(:part2) %>
|
152
|
-
#
|
153
|
-
# # Will generate the following in the final page...
|
154
|
-
# <html>
|
155
|
-
# <head>
|
156
|
-
# <script src="/javascripts/this.js" type="text/javascript"></script>
|
157
|
-
# <script src="/javascripts/something_else.js" type="text/javascript"></script>
|
158
|
-
# <link href="/stylesheets/that.css" media="all" rel="Stylesheet" type="text/css"/>
|
159
|
-
# <link href="/stylesheets/another_one.css" media="all" rel="Stylesheet" type="text/css"/>
|
160
|
-
# </head>
|
161
|
-
# .
|
162
|
-
# .
|
163
|
-
# .
|
164
|
-
# </html>
|
165
|
-
#
|
166
|
-
# See each method's documentation for more information.
|
167
|
-
|
168
|
-
# :section: Bundling Asset Files
|
169
|
-
#
|
170
|
-
# The key to making a fast web application is to reduce both the amount of
|
171
|
-
# data transfered and the number of client-server interactions. While having
|
172
|
-
# many small, module Javascript or stylesheet files aids in the development
|
173
|
-
# process, your web application will benefit from bundling those assets in
|
174
|
-
# the production environment.
|
175
|
-
#
|
176
|
-
# An asset bundle is a set of asset files which are combined into a single
|
177
|
-
# file. This reduces the number of requests required to render a page, and
|
178
|
-
# can reduce the amount of data transfer required if you're using gzip
|
179
|
-
# encoding.
|
180
|
-
#
|
181
|
-
# Asset bundling is always enabled in production mode, and can be optionally
|
182
|
-
# enabled in all environments by setting the <tt>:bundle_assets</tt> value
|
183
|
-
# in <tt>config/merb.yml</tt> to +true+.
|
184
|
-
#
|
185
|
-
# ==== Examples
|
186
|
-
#
|
187
|
-
# In the development environment, this:
|
188
|
-
#
|
189
|
-
# js_include_tag :prototype, :lowpro, :bundle => true
|
190
|
-
#
|
191
|
-
# will produce two <script> elements. In the production mode, however, the
|
192
|
-
# two files will be concatenated in the order given into a single file,
|
193
|
-
# <tt>all.js</tt>, in the <tt>public/javascripts</tt> directory.
|
194
|
-
#
|
195
|
-
# To specify a different bundle name:
|
196
|
-
#
|
197
|
-
# css_include_tag :typography, :whitespace, :bundle => :base
|
198
|
-
# css_include_tag :header, :footer, :bundle => "content"
|
199
|
-
# css_include_tag :lightbox, :images, :bundle => "lb.css"
|
200
|
-
#
|
201
|
-
# (<tt>base.css</tt>, <tt>content.css</tt>, and <tt>lb.css</tt> will all be
|
202
|
-
# created in the <tt>public/stylesheets</tt> directory.)
|
203
|
-
#
|
204
|
-
# == Callbacks
|
205
|
-
#
|
206
|
-
# To use a Javascript or CSS compressor, like JSMin or YUI Compressor:
|
207
|
-
#
|
208
|
-
# Merb::Assets::JavascriptAssetBundler.add_callback do |filename|
|
209
|
-
# system("/usr/local/bin/yui-compress #{filename}")
|
210
|
-
# end
|
211
|
-
#
|
212
|
-
# Merb::Assets::StylesheetAssetBundler.add_callback do |filename|
|
213
|
-
# system("/usr/local/bin/css-min #{filename}")
|
214
|
-
# end
|
215
|
-
#
|
216
|
-
# These blocks will be run after a bundle is created.
|
217
|
-
#
|
218
|
-
# == Bundling Required Assets
|
219
|
-
#
|
220
|
-
# Combining the +require_css+ and +require_js+ helpers with bundling can be
|
221
|
-
# problematic. You may want to separate out the common assets for your
|
222
|
-
# application -- Javascript frameworks, common CSS, etc. -- and bundle those
|
223
|
-
# in a "base" bundle. Then, for each section of your site, bundle the
|
224
|
-
# required assets into a section-specific bundle.
|
225
|
-
#
|
226
|
-
# <b>N.B.: If you bundle an inconsistent set of assets with the same name,
|
227
|
-
# you will have inconsistent results. Be thorough and test often.</b>
|
228
|
-
#
|
229
|
-
# ==== Example
|
230
|
-
#
|
231
|
-
# In your application layout:
|
232
|
-
#
|
233
|
-
# js_include_tag :prototype, :lowpro, :bundle => :base
|
234
|
-
#
|
235
|
-
# In your controller layout:
|
236
|
-
#
|
237
|
-
# require_js :bundle => :posts
|
238
|
-
|
239
|
-
# The require_js method can be used to require any JavaScript
|
240
|
-
# file anywhere in your templates. Regardless of how many times
|
241
|
-
# a single script is included with require_js, Merb will only include
|
242
|
-
# it once in the header.
|
243
|
-
#
|
244
|
-
# ==== Examples
|
245
|
-
# <% require_js 'jquery' %>
|
246
|
-
# # A subsequent call to include_required_js will render...
|
247
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
248
|
-
#
|
249
|
-
# <% require_js 'jquery', 'effects' %>
|
250
|
-
# # A subsequent call to include_required_js will render...
|
251
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
252
|
-
# # <script src="/javascripts/effects.js" type="text/javascript"></script>
|
253
|
-
#
|
254
|
-
def require_js(*js)
|
255
|
-
@required_js ||= []
|
256
|
-
@required_js |= js
|
257
|
-
end
|
258
|
-
|
259
|
-
# The require_css method can be used to require any CSS
|
260
|
-
# file anywhere in your templates. Regardless of how many times
|
261
|
-
# a single stylesheet is included with require_css, Merb will only include
|
262
|
-
# it once in the header.
|
263
|
-
#
|
264
|
-
# ==== Examples
|
265
|
-
# <% require_css('style') %>
|
266
|
-
# # A subsequent call to include_required_css will render...
|
267
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
268
|
-
#
|
269
|
-
# <% require_css('style', 'ie-specific') %>
|
270
|
-
# # A subsequent call to include_required_css will render...
|
271
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
272
|
-
# # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
|
273
|
-
#
|
274
|
-
def require_css(*css)
|
275
|
-
@required_css ||= []
|
276
|
-
@required_css |= css
|
277
|
-
end
|
278
|
-
|
279
|
-
# A method used in the layout of an application to create +<script>+ tags to include JavaScripts required in
|
280
|
-
# in templates and subtemplates using require_js.
|
281
|
-
#
|
282
|
-
# ==== Options
|
283
|
-
# bundle:: The name of the bundle the scripts should be combined into.
|
284
|
-
# If +nil+ or +false+, the bundle is not created. If +true+, a
|
285
|
-
# bundle named <tt>all.js</tt> is created. Otherwise,
|
286
|
-
# <tt>:bundle</tt> is treated as an asset name.
|
287
|
-
#
|
288
|
-
# ==== Examples
|
289
|
-
# # my_action.herb has a call to require_js 'jquery'
|
290
|
-
# # File: layout/application.html.erb
|
291
|
-
# include_required_js
|
292
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
293
|
-
#
|
294
|
-
# # my_action.herb has a call to require_js 'jquery', 'effects', 'validation'
|
295
|
-
# # File: layout/application.html.erb
|
296
|
-
# include_required_js
|
297
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
298
|
-
# # <script src="/javascripts/effects.js" type="text/javascript"></script>
|
299
|
-
# # <script src="/javascripts/validation.js" type="text/javascript"></script>
|
300
|
-
#
|
301
|
-
def include_required_js(options = {})
|
302
|
-
return '' if @required_js.nil?
|
303
|
-
js_include_tag(*(@required_js + [options]))
|
304
|
-
end
|
305
|
-
|
306
|
-
# A method used in the layout of an application to create +<link>+ tags for CSS stylesheets required in
|
307
|
-
# in templates and subtemplates using require_css.
|
308
|
-
#
|
309
|
-
# ==== Options
|
310
|
-
# bundle:: The name of the bundle the stylesheets should be combined into.
|
311
|
-
# If +nil+ or +false+, the bundle is not created. If +true+, a
|
312
|
-
# bundle named <tt>all.css</tt> is created. Otherwise,
|
313
|
-
# <tt>:bundle</tt> is treated as an asset name.
|
314
|
-
#
|
315
|
-
# ==== Examples
|
316
|
-
# # my_action.herb has a call to require_css 'style'
|
317
|
-
# # File: layout/application.html.erb
|
318
|
-
# include_required_css
|
319
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
320
|
-
#
|
321
|
-
# # my_action.herb has a call to require_js 'style', 'ie-specific'
|
322
|
-
# # File: layout/application.html.erb
|
323
|
-
# include_required_css
|
324
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css"/>
|
325
|
-
# # <link href="/stylesheets/ie-specific.css" media="all" rel="Stylesheet" type="text/css"/>
|
326
|
-
#
|
327
|
-
def include_required_css(options = {})
|
328
|
-
return '' if @required_css.nil?
|
329
|
-
css_include_tag(*(@required_css + [options]))
|
330
|
-
end
|
331
|
-
|
332
|
-
# The js_include_tag method will create a JavaScript
|
333
|
-
# +<include>+ tag for each script named in the arguments, appending
|
334
|
-
# '.js' if it is left out of the call.
|
335
|
-
#
|
336
|
-
# ==== Options
|
337
|
-
# bundle:: The name of the bundle the scripts should be combined into.
|
338
|
-
# If +nil+ or +false+, the bundle is not created. If +true+, a
|
339
|
-
# bundle named <tt>all.js</tt> is created. Otherwise,
|
340
|
-
# <tt>:bundle</tt> is treated as an asset name.
|
341
|
-
#
|
342
|
-
# ==== Examples
|
343
|
-
# js_include_tag 'jquery'
|
344
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
345
|
-
#
|
346
|
-
# js_include_tag 'moofx.js', 'upload'
|
347
|
-
# # => <script src="/javascripts/moofx.js" type="text/javascript"></script>
|
348
|
-
# # <script src="/javascripts/upload.js" type="text/javascript"></script>
|
349
|
-
#
|
350
|
-
# js_include_tag :effects
|
351
|
-
# # => <script src="/javascripts/effects.js" type="text/javascript"></script>
|
352
|
-
#
|
353
|
-
# js_include_tag :jquery, :validation
|
354
|
-
# # => <script src="/javascripts/jquery.js" type="text/javascript"></script>
|
355
|
-
# # <script src="/javascripts/validation.js" type="text/javascript"></script>
|
356
|
-
#
|
357
|
-
def js_include_tag(*scripts)
|
358
|
-
options = scripts.last.is_a?(Hash) ? scripts.pop : {}
|
359
|
-
return nil if scripts.empty?
|
360
|
-
|
361
|
-
if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && scripts.size > 1
|
362
|
-
bundler = Merb::Assets::JavascriptAssetBundler.new(bundle_name, *scripts)
|
363
|
-
bundled_asset = bundler.bundle!
|
364
|
-
return js_include_tag(bundled_asset)
|
365
|
-
end
|
366
|
-
|
367
|
-
tags = ""
|
368
|
-
|
369
|
-
for script in scripts
|
370
|
-
attrs = {
|
371
|
-
:src => asset_path(:javascript, script),
|
372
|
-
:type => "text/javascript"
|
373
|
-
}
|
374
|
-
tags << %Q{<script #{attrs.to_xml_attributes}>//</script>}
|
375
|
-
end
|
376
|
-
|
377
|
-
return tags
|
378
|
-
end
|
379
|
-
|
380
|
-
# The css_include_tag method will create a CSS stylesheet
|
381
|
-
# +<link>+ tag for each stylesheet named in the arguments, appending
|
382
|
-
# '.css' if it is left out of the call.
|
383
|
-
#
|
384
|
-
# ==== Options
|
385
|
-
# bundle:: The name of the bundle the stylesheets should be combined into.
|
386
|
-
# If +nil+ or +false+, the bundle is not created. If +true+, a
|
387
|
-
# bundle named <tt>all.css</tt> is created. Otherwise,
|
388
|
-
# <tt>:bundle</tt> is treated as an asset name.
|
389
|
-
# media:: The media attribute for the generated link element. Defaults
|
390
|
-
# to <tt>:all</tt>.
|
391
|
-
#
|
392
|
-
# ==== Examples
|
393
|
-
# css_include_tag 'style'
|
394
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />
|
395
|
-
#
|
396
|
-
# css_include_tag 'style.css', 'layout'
|
397
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />
|
398
|
-
# # <link href="/stylesheets/layout.css" media="all" rel="Stylesheet" type="text/css" />
|
399
|
-
#
|
400
|
-
# css_include_tag :menu
|
401
|
-
# # => <link href="/stylesheets/menu.css" media="all" rel="Stylesheet" type="text/css" />
|
402
|
-
#
|
403
|
-
# css_include_tag :style, :screen
|
404
|
-
# # => <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />
|
405
|
-
# # <link href="/stylesheets/screen.css" media="all" rel="Stylesheet" type="text/css" />
|
406
|
-
#
|
407
|
-
# css_include_tag :style, :media => :print
|
408
|
-
# # => <link href="/stylesheets/style.css" media="print" rel="Stylesheet" type="text/css" />
|
409
|
-
def css_include_tag(*stylesheets)
|
410
|
-
options = stylesheets.last.is_a?(Hash) ? stylesheets.pop : {}
|
411
|
-
return nil if stylesheets.empty?
|
412
|
-
|
413
|
-
if (bundle_name = options[:bundle]) && Merb::Assets.bundle? && stylesheets.size > 1
|
414
|
-
bundler = Merb::Assets::StylesheetAssetBundler.new(bundle_name, *stylesheets)
|
415
|
-
bundled_asset = bundler.bundle!
|
416
|
-
return css_include_tag(bundled_asset)
|
417
|
-
end
|
418
|
-
|
419
|
-
tags = ""
|
420
|
-
|
421
|
-
for stylesheet in stylesheets
|
422
|
-
attrs = {
|
423
|
-
:href => asset_path(:stylesheet, stylesheet),
|
424
|
-
:type => "text/css",
|
425
|
-
:rel => "Stylesheet",
|
426
|
-
:media => options[:media] || :all
|
427
|
-
}
|
428
|
-
tags << %Q{<link #{attrs.to_xml_attributes} />}
|
429
|
-
end
|
430
|
-
|
431
|
-
return tags
|
432
|
-
end
|
433
|
-
|
434
|
-
# :section: Caching
|
435
|
-
# ViewContextMixin provides views with fragment caching facilities.
|
436
|
-
|
437
|
-
# The cache method is a simple helper method
|
438
|
-
# for caching template fragments. The value of the supplied
|
439
|
-
# block is stored in the cache and identified by the string
|
440
|
-
# in the +name+ argument.
|
441
|
-
#
|
442
|
-
# ==== Example
|
443
|
-
# <h1>Article list</h1>
|
444
|
-
#
|
445
|
-
# <% cache(:article_list) do %>
|
446
|
-
# <ul>
|
447
|
-
# <% @articles.each do |a| %>
|
448
|
-
# <li><%= a.title %></li>
|
449
|
-
# <% end %>
|
450
|
-
# </ul>
|
451
|
-
# <% end %>
|
452
|
-
#
|
453
|
-
# See the documentation for Merb::Caching::Fragment for more
|
454
|
-
# information.
|
455
|
-
#
|
456
|
-
def cache(name, &block)
|
457
|
-
return block.call unless caching_enabled?
|
458
|
-
buffer = eval("_buf", block.binding)
|
459
|
-
if fragment = ::Merb::Caching::Fragment.get(name)
|
460
|
-
buffer.concat(fragment)
|
461
|
-
else
|
462
|
-
pos = buffer.length
|
463
|
-
block.call
|
464
|
-
::Merb::Caching::Fragment.put(name, buffer[pos..-1])
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
# Calling throw_content stores the block of markup for later use.
|
469
|
-
# Subsequently, you can make calls to it by name with <tt>catch_content</tt>
|
470
|
-
# in another template or in the layout.
|
471
|
-
#
|
472
|
-
# Example:
|
473
|
-
#
|
474
|
-
# <% throw_content :header do %>
|
475
|
-
# alert('hello world')
|
476
|
-
# <% end %>
|
477
|
-
#
|
478
|
-
# You can use catch_content :header anywhere in your templates.
|
479
|
-
#
|
480
|
-
# <%= catch_content :header %>
|
481
|
-
#
|
482
|
-
# You may find that you have trouble using thrown content inside a helper method
|
483
|
-
# There are a couple of mechanisms to get around this.
|
484
|
-
#
|
485
|
-
# 1. Pass the content in as a string instead of a block
|
486
|
-
#
|
487
|
-
# Example:
|
488
|
-
#
|
489
|
-
# throw_content(:header, "Hello World")
|
490
|
-
#
|
491
|
-
def throw_content(name, content = "", &block)
|
492
|
-
content << capture(&block) if block_given?
|
493
|
-
controller.thrown_content[name] << content
|
494
|
-
end
|
495
|
-
|
496
|
-
# Concat will concatenate text directly to the buffer of the template.
|
497
|
-
# The binding must be supplied in order to obtian the buffer. This can be called directly in the
|
498
|
-
# template as
|
499
|
-
# concat( "text", binding )
|
500
|
-
#
|
501
|
-
# or from a helper method that accepts a block as
|
502
|
-
# concat( "text", block.binding )
|
503
|
-
def concat( string, binding )
|
504
|
-
_buffer( binding ) << string
|
505
|
-
end
|
506
|
-
|
507
|
-
# Creates a generic HTML tag. You can invoke it a variety of ways.
|
508
|
-
#
|
509
|
-
# tag :div
|
510
|
-
# # <div></div>
|
511
|
-
#
|
512
|
-
# tag :div, 'content'
|
513
|
-
# # <div>content</div>
|
514
|
-
#
|
515
|
-
# tag :div, :class => 'class'
|
516
|
-
# # <div class="class"></div>
|
517
|
-
#
|
518
|
-
# tag :div, 'content', :class => 'class'
|
519
|
-
# # <div class="class">content</div>
|
520
|
-
#
|
521
|
-
# tag :div do
|
522
|
-
# 'content'
|
523
|
-
# end
|
524
|
-
# # <div>content</div>
|
525
|
-
#
|
526
|
-
# tag :div, :class => 'class' do
|
527
|
-
# 'content'
|
528
|
-
# end
|
529
|
-
# # <div class="class">content</div>
|
530
|
-
#
|
531
|
-
def tag(name, contents = nil, attrs = {}, &block)
|
532
|
-
attrs = contents if contents.is_a?(Hash)
|
533
|
-
contents = capture(&block) if block_given?
|
534
|
-
open_tag(name, attrs) + contents.to_s + close_tag(name)
|
535
|
-
end
|
536
|
-
|
537
|
-
# Creates the opening tag with attributes for the provided +name+
|
538
|
-
# attrs is a hash where all members will be mapped to key="value"
|
539
|
-
#
|
540
|
-
# Note: This tag will need to be closed
|
541
|
-
def open_tag(name, attrs = nil)
|
542
|
-
"<#{name}#{' ' + attrs.to_html_attributes if attrs && !attrs.empty?}>"
|
543
|
-
end
|
544
|
-
|
545
|
-
# Creates a closing tag
|
546
|
-
def close_tag(name)
|
547
|
-
"</#{name}>"
|
548
|
-
end
|
549
|
-
|
550
|
-
# Creates a self closing tag. Like <br/> or <img src="..."/>
|
551
|
-
#
|
552
|
-
# +name+ : the name of the tag to create
|
553
|
-
# +attrs+ : a hash where all members will be mapped to key="value"
|
554
|
-
def self_closing_tag(name, attrs = nil)
|
555
|
-
"<#{name}#{' ' + attrs.to_html_attributes if attrs && !attrs.empty?}/>"
|
556
|
-
end
|
557
|
-
end
|
558
|
-
end
|