thorero-core 0.9.4.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +21 -0
- data/Rakefile +352 -0
- data/TODO +0 -0
- data/bin/merb +12 -0
- data/bin/merb-specs +5 -0
- data/docs/bootloading.dox +58 -0
- data/docs/documentation_standards +40 -0
- data/docs/merb-core-call-stack-diagram.mmap +0 -0
- data/docs/merb-core-call-stack-diagram.pdf +0 -0
- data/docs/merb-core-call-stack-diagram.png +0 -0
- data/docs/new_render_api +51 -0
- data/lib/merb-core.rb +603 -0
- data/lib/merb-core/autoload.rb +32 -0
- data/lib/merb-core/bootloader.rb +708 -0
- data/lib/merb-core/config.rb +303 -0
- data/lib/merb-core/constants.rb +43 -0
- data/lib/merb-core/controller/abstract_controller.rb +578 -0
- data/lib/merb-core/controller/exceptions.rb +302 -0
- data/lib/merb-core/controller/merb_controller.rb +256 -0
- data/lib/merb-core/controller/mime.rb +106 -0
- data/lib/merb-core/controller/mixins/authentication.rb +87 -0
- data/lib/merb-core/controller/mixins/controller.rb +290 -0
- data/lib/merb-core/controller/mixins/render.rb +481 -0
- data/lib/merb-core/controller/mixins/responder.rb +472 -0
- data/lib/merb-core/controller/template.rb +254 -0
- data/lib/merb-core/core_ext.rb +8 -0
- data/lib/merb-core/core_ext/kernel.rb +319 -0
- data/lib/merb-core/dispatch/cookies.rb +91 -0
- data/lib/merb-core/dispatch/dispatcher.rb +278 -0
- data/lib/merb-core/dispatch/exceptions.html.erb +303 -0
- data/lib/merb-core/dispatch/request.rb +603 -0
- data/lib/merb-core/dispatch/router.rb +179 -0
- data/lib/merb-core/dispatch/router/behavior.rb +867 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/route.rb +321 -0
- data/lib/merb-core/dispatch/session.rb +78 -0
- data/lib/merb-core/dispatch/session/cookie.rb +168 -0
- data/lib/merb-core/dispatch/session/memcached.rb +184 -0
- data/lib/merb-core/dispatch/session/memory.rb +241 -0
- data/lib/merb-core/dispatch/worker.rb +28 -0
- data/lib/merb-core/gem_ext/erubis.rb +77 -0
- data/lib/merb-core/logger.rb +202 -0
- data/lib/merb-core/plugins.rb +59 -0
- data/lib/merb-core/rack.rb +21 -0
- data/lib/merb-core/rack/adapter.rb +44 -0
- data/lib/merb-core/rack/adapter/ebb.rb +25 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
- data/lib/merb-core/rack/adapter/irb.rb +118 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/runner.rb +28 -0
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/thin.rb +39 -0
- data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
- data/lib/merb-core/rack/adapter/webrick.rb +36 -0
- data/lib/merb-core/rack/application.rb +18 -0
- data/lib/merb-core/rack/handler/mongrel.rb +97 -0
- data/lib/merb-core/rack/middleware.rb +26 -0
- data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
- data/lib/merb-core/rack/middleware/profiler.rb +19 -0
- data/lib/merb-core/rack/middleware/static.rb +45 -0
- data/lib/merb-core/server.rb +252 -0
- data/lib/merb-core/tasks/audit.rake +68 -0
- data/lib/merb-core/tasks/merb.rb +1 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +12 -0
- data/lib/merb-core/test.rb +11 -0
- data/lib/merb-core/test/helpers.rb +9 -0
- data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
- data/lib/merb-core/test/helpers/request_helper.rb +344 -0
- data/lib/merb-core/test/helpers/route_helper.rb +33 -0
- data/lib/merb-core/test/helpers/view_helper.rb +121 -0
- data/lib/merb-core/test/matchers.rb +9 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +319 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +335 -0
- data/lib/merb-core/test/run_specs.rb +47 -0
- data/lib/merb-core/test/tasks/spectasks.rb +68 -0
- data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
- data/lib/merb-core/test/test_ext/object.rb +14 -0
- data/lib/merb-core/test/test_ext/string.rb +14 -0
- data/lib/merb-core/vendor/facets.rb +2 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
- data/lib/merb-core/vendor/facets/inflect.rb +345 -0
- data/lib/merb-core/version.rb +11 -0
- data/spec/private/config/adapter_spec.rb +32 -0
- data/spec/private/config/config_spec.rb +202 -0
- data/spec/private/config/environment_spec.rb +13 -0
- data/spec/private/config/spec_helper.rb +1 -0
- data/spec/private/core_ext/kernel_spec.rb +169 -0
- data/spec/private/dispatch/bootloader_spec.rb +24 -0
- data/spec/private/dispatch/cookies_spec.rb +107 -0
- data/spec/private/dispatch/dispatch_spec.rb +35 -0
- data/spec/private/dispatch/fixture/app/controllers/application.rb +4 -0
- data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +27 -0
- data/spec/private/dispatch/fixture/app/controllers/foo.rb +21 -0
- data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +8 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +37 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +40 -0
- data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
- data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +11 -0
- data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
- data/spec/private/dispatch/fixture/config/environments/development.rb +6 -0
- data/spec/private/dispatch/fixture/config/environments/production.rb +5 -0
- data/spec/private/dispatch/fixture/config/environments/test.rb +6 -0
- data/spec/private/dispatch/fixture/config/init.rb +45 -0
- data/spec/private/dispatch/fixture/config/rack.rb +11 -0
- data/spec/private/dispatch/fixture/config/router.rb +35 -0
- data/spec/private/dispatch/fixture/log/merb_test.log +1874 -0
- data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
- data/spec/private/dispatch/fixture/public/merb.fcgi +4 -0
- data/spec/private/dispatch/fixture/public/stylesheets/master.css +119 -0
- data/spec/private/dispatch/route_params_spec.rb +24 -0
- data/spec/private/dispatch/session_mixin_spec.rb +47 -0
- data/spec/private/dispatch/spec_helper.rb +1 -0
- data/spec/private/plugins/plugin_spec.rb +166 -0
- data/spec/private/rack/application_spec.rb +49 -0
- data/spec/private/router/behavior_spec.rb +60 -0
- data/spec/private/router/fixture/log/merb_test.log +139 -0
- data/spec/private/router/route_spec.rb +414 -0
- data/spec/private/router/router_spec.rb +175 -0
- data/spec/private/vendor/facets/plural_spec.rb +564 -0
- data/spec/private/vendor/facets/singular_spec.rb +489 -0
- data/spec/public/DEFINITIONS +11 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/cousins.rb +41 -0
- data/spec/public/abstract_controller/controllers/display.rb +54 -0
- data/spec/public/abstract_controller/controllers/filters.rb +193 -0
- data/spec/public/abstract_controller/controllers/helpers.rb +41 -0
- data/spec/public/abstract_controller/controllers/partial.rb +121 -0
- data/spec/public/abstract_controller/controllers/render.rb +113 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture_eq/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture_with_args/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/layout/alt.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/layout/custom.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_two_throw_contents/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_counter/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_absolute_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
- data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +1 -0
- data/spec/public/abstract_controller/display_spec.rb +33 -0
- data/spec/public/abstract_controller/filter_spec.rb +106 -0
- data/spec/public/abstract_controller/helper_spec.rb +21 -0
- data/spec/public/abstract_controller/partial_spec.rb +61 -0
- data/spec/public/abstract_controller/render_spec.rb +90 -0
- data/spec/public/abstract_controller/spec_helper.rb +31 -0
- data/spec/public/boot_loader/boot_loader_spec.rb +33 -0
- data/spec/public/boot_loader/spec_helper.rb +1 -0
- data/spec/public/controller/authentication_spec.rb +103 -0
- data/spec/public/controller/base_spec.rb +36 -0
- data/spec/public/controller/controllers/authentication.rb +45 -0
- data/spec/public/controller/controllers/base.rb +36 -0
- data/spec/public/controller/controllers/display.rb +118 -0
- data/spec/public/controller/controllers/redirect.rb +30 -0
- data/spec/public/controller/controllers/responder.rb +93 -0
- data/spec/public/controller/controllers/url.rb +7 -0
- data/spec/public/controller/controllers/views/layout/custom.html.erb +1 -0
- data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
- data/spec/public/controller/controllers/views/layout/custom_arg.json.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_and_local_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/no_layout.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +1 -0
- data/spec/public/controller/display_spec.rb +84 -0
- data/spec/public/controller/redirect_spec.rb +27 -0
- data/spec/public/controller/responder_spec.rb +163 -0
- data/spec/public/controller/spec_helper.rb +11 -0
- data/spec/public/controller/url_spec.rb +180 -0
- data/spec/public/core/merb_core_spec.rb +45 -0
- data/spec/public/core_ext/class_spec.rb +91 -0
- data/spec/public/core_ext/fixtures/core_ext_dependency.rb +2 -0
- data/spec/public/core_ext/kernel_spec.rb +9 -0
- data/spec/public/core_ext/spec_helper.rb +1 -0
- data/spec/public/directory_structure/directory/app/controllers/application.rb +3 -0
- data/spec/public/directory_structure/directory/app/controllers/base.rb +13 -0
- data/spec/public/directory_structure/directory/app/controllers/custom.rb +19 -0
- data/spec/public/directory_structure/directory/app/views/base/template.html.erb +1 -0
- data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +1 -0
- data/spec/public/directory_structure/directory/config/router.rb +3 -0
- data/spec/public/directory_structure/directory/log/merb_test.log +562 -0
- data/spec/public/directory_structure/directory_spec.rb +44 -0
- data/spec/public/logger/logger_spec.rb +181 -0
- data/spec/public/logger/spec_helper.rb +1 -0
- data/spec/public/reloading/directory/app/controllers/application.rb +3 -0
- data/spec/public/reloading/directory/app/controllers/reload.rb +6 -0
- data/spec/public/reloading/directory/config/init.rb +2 -0
- data/spec/public/reloading/directory/log/merb_test.log +138 -0
- data/spec/public/reloading/reload_spec.rb +103 -0
- data/spec/public/request/multipart_spec.rb +41 -0
- data/spec/public/request/request_spec.rb +228 -0
- data/spec/public/router/default_spec.rb +21 -0
- data/spec/public/router/deferred_spec.rb +22 -0
- data/spec/public/router/fixation_spec.rb +27 -0
- data/spec/public/router/fixture/log/merb_test.log +1556 -0
- data/spec/public/router/namespace_spec.rb +113 -0
- data/spec/public/router/nested_matches_spec.rb +97 -0
- data/spec/public/router/nested_resources_spec.rb +41 -0
- data/spec/public/router/resource_spec.rb +37 -0
- data/spec/public/router/resources_spec.rb +82 -0
- data/spec/public/router/spec_helper.rb +90 -0
- data/spec/public/router/special_spec.rb +61 -0
- data/spec/public/router/string_spec.rb +61 -0
- data/spec/public/template/template_spec.rb +104 -0
- data/spec/public/template/templates/error.html.erb +2 -0
- data/spec/public/template/templates/template.html.erb +1 -0
- data/spec/public/template/templates/template.html.myt +1 -0
- data/spec/public/test/controller_matchers_spec.rb +402 -0
- data/spec/public/test/controllers/controller_assertion_mock.rb +7 -0
- data/spec/public/test/controllers/dispatch_controller.rb +11 -0
- data/spec/public/test/controllers/spec_helper_controller.rb +38 -0
- data/spec/public/test/multipart_request_helper_spec.rb +159 -0
- data/spec/public/test/multipart_upload_text_file.txt +1 -0
- data/spec/public/test/request_helper_spec.rb +221 -0
- data/spec/public/test/route_helper_spec.rb +71 -0
- data/spec/public/test/route_matchers_spec.rb +162 -0
- data/spec/public/test/view_helper_spec.rb +96 -0
- data/spec/public/test/view_matchers_spec.rb +183 -0
- data/spec/spec_helper.rb +68 -0
- metadata +542 -0
@@ -0,0 +1,303 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
module Merb
|
5
|
+
|
6
|
+
class Config
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# ==== Returns
|
11
|
+
# Hash:: The defaults for the config.
|
12
|
+
def defaults
|
13
|
+
@defaults ||= {
|
14
|
+
:host => "0.0.0.0",
|
15
|
+
:port => "4000",
|
16
|
+
:adapter => "runner",
|
17
|
+
:reload_classes => true,
|
18
|
+
:environment => "development",
|
19
|
+
:merb_root => Dir.pwd,
|
20
|
+
:use_mutex => true,
|
21
|
+
:session_id_key => "_session_id",
|
22
|
+
:log_delimiter => " ~ ",
|
23
|
+
:log_auto_flush => false,
|
24
|
+
:log_level => :info,
|
25
|
+
:disabled_components => [],
|
26
|
+
:deferred_actions => [],
|
27
|
+
:verbose => false
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Yields the configuration.
|
32
|
+
#
|
33
|
+
# ==== Block parameters
|
34
|
+
# c<Hash>:: The configuration parameters.
|
35
|
+
#
|
36
|
+
# ==== Examples
|
37
|
+
# Merb::Config.use do |config|
|
38
|
+
# config[:exception_details] = false
|
39
|
+
# end
|
40
|
+
def use
|
41
|
+
@configuration ||= {}
|
42
|
+
yield @configuration
|
43
|
+
end
|
44
|
+
|
45
|
+
# ==== Parameters
|
46
|
+
# key<Object>:: The key to check.
|
47
|
+
#
|
48
|
+
# ==== Returns
|
49
|
+
# Boolean:: True if the key exists in the config.
|
50
|
+
def key?(key)
|
51
|
+
@configuration.key?(key)
|
52
|
+
end
|
53
|
+
|
54
|
+
# ==== Parameters
|
55
|
+
# key<Object>:: The key to retrieve the parameter for.
|
56
|
+
#
|
57
|
+
# ==== Returns
|
58
|
+
# Object:: The value of the configuration parameter.
|
59
|
+
def [](key)
|
60
|
+
(@configuration||={})[key]
|
61
|
+
end
|
62
|
+
|
63
|
+
# ==== Parameters
|
64
|
+
# key<Object>:: The key to set the parameter for.
|
65
|
+
# val<Object>:: The value of the parameter.
|
66
|
+
def []=(key,val)
|
67
|
+
@configuration[key] = val
|
68
|
+
end
|
69
|
+
|
70
|
+
# ==== Parameters
|
71
|
+
# key<Object>:: The key of the parameter to delete.
|
72
|
+
def delete(key)
|
73
|
+
@configuration.delete(key)
|
74
|
+
end
|
75
|
+
|
76
|
+
# ==== Parameters
|
77
|
+
# key<Object>:: The key to retrieve the parameter for.
|
78
|
+
# default<Object>::
|
79
|
+
# The default value to return if the parameter is not set.
|
80
|
+
#
|
81
|
+
# ==== Returns
|
82
|
+
# Object:: The value of the configuration parameter or the default.
|
83
|
+
def fetch(key, default)
|
84
|
+
@configuration.fetch(key, default)
|
85
|
+
end
|
86
|
+
|
87
|
+
# ==== Returns
|
88
|
+
# Hash:: The config as a hash.
|
89
|
+
def to_hash
|
90
|
+
@configuration
|
91
|
+
end
|
92
|
+
|
93
|
+
# ==== Returns
|
94
|
+
# String:: The config as YAML.
|
95
|
+
def to_yaml
|
96
|
+
@configuration.to_yaml
|
97
|
+
end
|
98
|
+
|
99
|
+
# Sets up the configuration by storing the given settings.
|
100
|
+
#
|
101
|
+
# ==== Parameters
|
102
|
+
# settings<Hash>::
|
103
|
+
# Configuration settings to use. These are merged with the defaults.
|
104
|
+
def setup(settings = {})
|
105
|
+
@configuration = defaults.merge(settings)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Parses the command line arguments and stores them in the config.
|
109
|
+
#
|
110
|
+
# ==== Parameters
|
111
|
+
# argv<String>:: The command line arguments. Defaults to +ARGV+.
|
112
|
+
def parse_args(argv = ARGV)
|
113
|
+
@configuration ||= {}
|
114
|
+
# Our primary configuration hash for the length of this method
|
115
|
+
options = {}
|
116
|
+
|
117
|
+
# Environment variables always win
|
118
|
+
options[:environment] = ENV["MERB_ENV"] if ENV["MERB_ENV"]
|
119
|
+
|
120
|
+
# Build a parser for the command line arguments
|
121
|
+
opts = OptionParser.new do |opts|
|
122
|
+
opts.version = Merb::VERSION
|
123
|
+
opts.release = Merb::RELEASE
|
124
|
+
|
125
|
+
opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]"
|
126
|
+
opts.define_head "Merb. Pocket rocket web framework"
|
127
|
+
opts.separator '*'*80
|
128
|
+
opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
|
129
|
+
opts.separator '*'*80
|
130
|
+
|
131
|
+
opts.on("-u", "--user USER", "This flag is for having merb run as a user other than the one currently logged in. Note: if you set this you must also provide a --group option for it to take effect.") do |user|
|
132
|
+
options[:user] = user
|
133
|
+
end
|
134
|
+
|
135
|
+
opts.on("-G", "--group GROUP", "This flag is for having merb run as a group other than the one currently logged in. Note: if you set this you must also provide a --user option for it to take effect.") do |group|
|
136
|
+
options[:group] = group
|
137
|
+
end
|
138
|
+
|
139
|
+
opts.on("-d", "--daemonize", "This will run a single merb in the background.") do |daemon|
|
140
|
+
options[:daemonize] = true
|
141
|
+
end
|
142
|
+
|
143
|
+
opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run.") do |nodes|
|
144
|
+
options[:cluster] = nodes
|
145
|
+
end
|
146
|
+
|
147
|
+
opts.on("-I", "--init-file FILE", "File to use for initialization on load, defaults to config/init.rb") do |init_file|
|
148
|
+
options[:init_file] = init_file
|
149
|
+
end
|
150
|
+
|
151
|
+
opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
|
152
|
+
options[:port] = port
|
153
|
+
end
|
154
|
+
|
155
|
+
opts.on("-o", "--socket-file FILE", "Socket file to run merb on, defaults to [Merb.root]/log/merb.sock") do |port|
|
156
|
+
options[:socket_file] = port
|
157
|
+
end
|
158
|
+
|
159
|
+
opts.on("-s", "--socket SOCKNUM", "Socket number to run merb on, defaults to 0.") do |port|
|
160
|
+
options[:socket] = port
|
161
|
+
end
|
162
|
+
|
163
|
+
opts.on("-P", "--pid PIDFILE", "PID file, defaults to [Merb.root]/log/merb.[port_number].pid") do |pid_file|
|
164
|
+
options[:pid_file] = pid_file
|
165
|
+
end
|
166
|
+
|
167
|
+
opts.on("-h", "--host HOSTNAME", "Host to bind to (default is 0.0.0.0).") do |host|
|
168
|
+
options[:host] = host
|
169
|
+
end
|
170
|
+
|
171
|
+
opts.on("-m", "--merb-root /path/to/approot", "The path to the Merb.root for the app you want to run (default is current working dir).") do |root|
|
172
|
+
options[:merb_root] = File.expand_path(root)
|
173
|
+
end
|
174
|
+
|
175
|
+
opts.on("-a", "--adapter mongrel", "The rack adapter to use to run merb[mongrel, emongrel, thin, ebb, fastcgi, webrick, runner, irb]") do |adapter|
|
176
|
+
options[:adapter] = adapter
|
177
|
+
end
|
178
|
+
|
179
|
+
opts.on("-R", "--rackup FILE", "Load an alternate Rack config file (default is config/rack.rb)") do |rackup|
|
180
|
+
options[:rackup] = rackup
|
181
|
+
end
|
182
|
+
|
183
|
+
opts.on("-i", "--irb-console", "This flag will start merb in irb console mode. All your models and other classes will be available for you in an irb session.") do |console|
|
184
|
+
options[:adapter] = 'irb'
|
185
|
+
end
|
186
|
+
|
187
|
+
opts.on("-S", "--sandbox", "This flag will enable a sandboxed irb console. If your ORM supports transactions, all edits will be rolled back on exit.") do |sandbox|
|
188
|
+
options[:sandbox] = true
|
189
|
+
end
|
190
|
+
|
191
|
+
opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of these options: debug < info < warn < error < fatal") do |log_level|
|
192
|
+
options[:log_level] = log_level.to_sym
|
193
|
+
end
|
194
|
+
|
195
|
+
opts.on("-L", "--log LOGFILE", "A string representing the logfile to use.") do |log_file|
|
196
|
+
options[:log_file] = log_file
|
197
|
+
end
|
198
|
+
|
199
|
+
opts.on("-e", "--environment STRING", "Run merb in the correct mode(development, production, testing)") do |env|
|
200
|
+
options[:environment] = env
|
201
|
+
end
|
202
|
+
|
203
|
+
opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
|
204
|
+
"Command-line option to run scripts and/or code in the merb app.") do |code_or_file|
|
205
|
+
options[:runner_code] = code_or_file
|
206
|
+
options[:adapter] = 'runner'
|
207
|
+
end
|
208
|
+
|
209
|
+
opts.on("-K", "--graceful PORT or all", "Gracefully kill one merb proceses by port number. Use merb -K all to gracefully kill all merbs.") do |ports|
|
210
|
+
options[:action] = :kill
|
211
|
+
options[:port] = ports
|
212
|
+
end
|
213
|
+
|
214
|
+
opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. Use merb -k all to kill all merbs.") do |port|
|
215
|
+
options[:action] = :kill_9
|
216
|
+
options[:port] = port
|
217
|
+
end
|
218
|
+
|
219
|
+
opts.on("-X", "--mutex on/off", "This flag is for turning the mutex lock on and off.") do |mutex|
|
220
|
+
if mutex == "off"
|
221
|
+
options[:use_mutex] = false
|
222
|
+
else
|
223
|
+
options[:use_mutex] = true
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
opts.on("-D", "--debugger", "Run merb using rDebug.") do
|
228
|
+
begin
|
229
|
+
require "ruby-debug"
|
230
|
+
Debugger.start
|
231
|
+
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
232
|
+
puts "Debugger enabled"
|
233
|
+
rescue LoadError
|
234
|
+
puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
|
235
|
+
exit
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
opts.on("-V", "--verbose", "Print extra information") do
|
240
|
+
options[:verbose] = true
|
241
|
+
end
|
242
|
+
|
243
|
+
opts.on("-?", "-H", "--help", "Show this help message") do
|
244
|
+
puts opts
|
245
|
+
exit
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# Parse what we have on the command line
|
250
|
+
opts.parse!(argv)
|
251
|
+
Merb::Config.setup(options)
|
252
|
+
end
|
253
|
+
|
254
|
+
attr_accessor :configuration
|
255
|
+
|
256
|
+
# Set configuration parameters from a code block, where each method
|
257
|
+
# evaluates to a config parameter.
|
258
|
+
#
|
259
|
+
# ==== Parameters
|
260
|
+
# &block:: Configuration parameter block.
|
261
|
+
#
|
262
|
+
# ==== Examples
|
263
|
+
# # Set environment and log level.
|
264
|
+
# Merb::Config.configure do
|
265
|
+
# environment "development"
|
266
|
+
# log_level "debug"
|
267
|
+
# end
|
268
|
+
def configure(&block)
|
269
|
+
ConfigBlock.new(self, &block) if block_given?
|
270
|
+
end
|
271
|
+
|
272
|
+
# Allows retrieval of single key config values via Merb.config.<key>
|
273
|
+
# Allows single key assignment via Merb.config.<key> = ...
|
274
|
+
#
|
275
|
+
# ==== Parameters
|
276
|
+
# method<~to_s>:: Method name as hash key value.
|
277
|
+
# *args:: Value to set the configuration parameter to.
|
278
|
+
def method_missing(method, *args)
|
279
|
+
if method.to_s[-1,1] == '='
|
280
|
+
@configuration[method.to_s.tr('=','').to_sym] = *args
|
281
|
+
else
|
282
|
+
@configuration[method]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end # class << self
|
287
|
+
|
288
|
+
class ConfigBlock
|
289
|
+
|
290
|
+
def initialize(klass, &block)
|
291
|
+
@klass = klass
|
292
|
+
instance_eval(&block)
|
293
|
+
end
|
294
|
+
|
295
|
+
def method_missing(method, *args)
|
296
|
+
@klass[method] = *args
|
297
|
+
end
|
298
|
+
|
299
|
+
end # class Configurator
|
300
|
+
|
301
|
+
end # Config
|
302
|
+
|
303
|
+
end # Merb
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Most of this list is simply constants frozen for efficiency
|
2
|
+
module Merb
|
3
|
+
module Const
|
4
|
+
|
5
|
+
DEFAULT_SEND_FILE_OPTIONS = {
|
6
|
+
:type => 'application/octet-stream'.freeze,
|
7
|
+
:disposition => 'attachment'.freeze
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
SET_COOKIE = " %s=%s; path=/; expires=%s".freeze
|
11
|
+
COOKIE_EXPIRATION_FORMAT = "%a, %d-%b-%Y %H:%M:%S GMT".freeze
|
12
|
+
COOKIE_SPLIT = /[;,] */n.freeze
|
13
|
+
COOKIE_REGEXP = /\s*(.+)=(.*)\s*/.freeze
|
14
|
+
COOKIE_EXPIRED_TIME = Time.at(0).freeze
|
15
|
+
HOUR = 60 * 60
|
16
|
+
DAY = HOUR * 24
|
17
|
+
WEEK = DAY * 7
|
18
|
+
MULTIPART_REGEXP = /\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze
|
19
|
+
HTTP_COOKIE = 'HTTP_COOKIE'.freeze
|
20
|
+
QUERY_STRING = 'QUERY_STRING'.freeze
|
21
|
+
JSON_MIME_TYPE_REGEXP = %r{^application/json|^text/x-json}.freeze
|
22
|
+
XML_MIME_TYPE_REGEXP = %r{^application/xml|^text/xml}.freeze
|
23
|
+
FORM_URL_ENCODED_REGEXP = %r{^application/x-www-form-urlencoded}.freeze
|
24
|
+
UPCASE_CONTENT_TYPE = 'CONTENT_TYPE'.freeze
|
25
|
+
CONTENT_TYPE = "Content-Type".freeze
|
26
|
+
LAST_MODIFIED = "Last-Modified".freeze
|
27
|
+
SLASH = "/".freeze
|
28
|
+
REQUEST_METHOD = "REQUEST_METHOD".freeze
|
29
|
+
GET = "GET".freeze
|
30
|
+
POST = "POST".freeze
|
31
|
+
HEAD = "HEAD".freeze
|
32
|
+
CONTENT_LENGTH = "CONTENT_LENGTH".freeze
|
33
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
|
34
|
+
HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
|
35
|
+
HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
|
36
|
+
UPLOAD_ID = "upload_id".freeze
|
37
|
+
PATH_INFO = "PATH_INFO".freeze
|
38
|
+
SCRIPT_NAME = "SCRIPT_NAME".freeze
|
39
|
+
REQUEST_URI = "REQUEST_URI".freeze
|
40
|
+
REQUEST_PATH = "REQUEST_PATH".freeze
|
41
|
+
REMOTE_ADDR = "REMOTE_ADDR".freeze
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,578 @@
|
|
1
|
+
# ==== Why do we use Underscores?
|
2
|
+
# In Merb, views are actually methods on controllers. This provides
|
3
|
+
# not-insignificant speed benefits, as well as preventing us from
|
4
|
+
# needing to copy over instance variables, which we think is proof
|
5
|
+
# that everything belongs in one class to begin with.
|
6
|
+
#
|
7
|
+
# Unfortunately, this means that view helpers need to be included
|
8
|
+
# into the <strong>Controller</strong> class. To avoid causing confusion
|
9
|
+
# when your helpers potentially conflict with our instance methods,
|
10
|
+
# we use an _ to disambiguate. As long as you don't begin your helper
|
11
|
+
# methods with _, you only need to worry about conflicts with Merb
|
12
|
+
# methods that are part of the public API.
|
13
|
+
#
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# ==== Filters
|
17
|
+
# #before is a class method that allows you to specify before filters in
|
18
|
+
# your controllers. Filters can either be a symbol or string that
|
19
|
+
# corresponds to a method name to call, or a proc object. if it is a method
|
20
|
+
# name that method will be called and if it is a proc it will be called
|
21
|
+
# with an argument of self where self is the current controller object.
|
22
|
+
# When you use a proc as a filter it needs to take one parameter.
|
23
|
+
#
|
24
|
+
# #after is identical, but the filters are run after the action is invoked.
|
25
|
+
#
|
26
|
+
# ===== Examples
|
27
|
+
# before :some_filter
|
28
|
+
# before :authenticate, :exclude => [:login, :signup]
|
29
|
+
# before :has_role, :with => ["Admin"], :exclude => [:index,:show]
|
30
|
+
# before Proc.new {|c| c.some_method }, :only => :foo
|
31
|
+
# before :authorize, :unless => logged_in?
|
32
|
+
#
|
33
|
+
# You can use either :only => :actionname or :exclude => [:this, :that]
|
34
|
+
# but not both at once. :only will only run before the listed actions
|
35
|
+
# and :exclude will run for every action that is not listed.
|
36
|
+
#
|
37
|
+
# Merb's before filter chain is very flexible. To halt the filter chain you
|
38
|
+
# use throw :halt. If throw is called with only one argument of :halt the
|
39
|
+
# return of the method filters_halted will be what is rendered to the view.
|
40
|
+
# You can overide filters_halted in your own controllers to control what it
|
41
|
+
# outputs. But the throw construct is much more powerful then just that.
|
42
|
+
# throw :halt can also take a second argument. Here is what that second arg
|
43
|
+
# can be and the behavior each type can have:
|
44
|
+
#
|
45
|
+
# * +String+:
|
46
|
+
# when the second arg is a string then that string will be what
|
47
|
+
# is rendered to the browser. Since merb's render method returns
|
48
|
+
# a string you can render a template or just use a plain string:
|
49
|
+
#
|
50
|
+
# throw :halt, "You don't have permissions to do that!"
|
51
|
+
# throw :halt, render(:action => :access_denied)
|
52
|
+
#
|
53
|
+
# * +Symbol+:
|
54
|
+
# If the second arg is a symbol then the method named after that
|
55
|
+
# symbol will be called
|
56
|
+
#
|
57
|
+
# throw :halt, :must_click_disclaimer
|
58
|
+
#
|
59
|
+
# * +Proc+:
|
60
|
+
#
|
61
|
+
# If the second arg is a Proc, it will be called and its return
|
62
|
+
# value will be what is rendered to the browser:
|
63
|
+
#
|
64
|
+
# throw :halt, proc {|c| c.access_denied }
|
65
|
+
# throw :halt, proc {|c| Tidy.new(c.index) }
|
66
|
+
#
|
67
|
+
# ===== Filter Options (.before, .after, .add_filter, .if, .unless)
|
68
|
+
# :only<Symbol, Array[Symbol]>::
|
69
|
+
# A list of actions that this filter should apply to
|
70
|
+
#
|
71
|
+
# :exclude<Symbol, Array[Symbol]::
|
72
|
+
# A list of actions that this filter should *not* apply to
|
73
|
+
#
|
74
|
+
# :if<Symbol, Proc>::
|
75
|
+
# Only apply the filter if the method named after the symbol or calling the proc evaluates to true
|
76
|
+
#
|
77
|
+
# :unless<Symbol, Proc>::
|
78
|
+
# Only apply the filter if the method named after the symbol or calling the proc evaluates to false
|
79
|
+
#
|
80
|
+
# ===== Types (shortcuts for use in this file)
|
81
|
+
# Filter:: <Array[Symbol, (Symbol, String, Proc)]>
|
82
|
+
#
|
83
|
+
# ==== params[:action] and params[:controller] deprecated
|
84
|
+
# params[:action] and params[:controller] have been deprecated as of
|
85
|
+
# the 0.9.0 release. They are no longer set during dispatch, and
|
86
|
+
# have been replaced by action_name and controller_name respectively.
|
87
|
+
class Merb::AbstractController
|
88
|
+
include Merb::RenderMixin
|
89
|
+
include Merb::InlineTemplates
|
90
|
+
|
91
|
+
class_inheritable_accessor :_layout, :_template_root, :template_roots
|
92
|
+
class_inheritable_accessor :_before_filters, :_after_filters
|
93
|
+
|
94
|
+
FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
|
95
|
+
|
96
|
+
# ==== Returns
|
97
|
+
# String:: The controller name in path form, e.g. "admin/items".
|
98
|
+
#---
|
99
|
+
# @public
|
100
|
+
def self.controller_name() @controller_name ||= self.name.to_const_path end
|
101
|
+
|
102
|
+
# ==== Returns
|
103
|
+
# String:: The controller name in path form, e.g. "admin/items".
|
104
|
+
def controller_name() self.class.controller_name end
|
105
|
+
|
106
|
+
self._before_filters, self._after_filters = [], []
|
107
|
+
|
108
|
+
# This is called after the controller is instantiated to figure out where to
|
109
|
+
# for templates under the _template_root. Override this to define a new
|
110
|
+
# structure for your app.
|
111
|
+
#
|
112
|
+
# ==== Parameters
|
113
|
+
# context<~to_s>:: The controller context (the action or template name).
|
114
|
+
# type<~to_s>:: The content type. Defaults to nil.
|
115
|
+
# controller<~to_s>::
|
116
|
+
# The name of the controller. Defaults to controller_name.
|
117
|
+
#
|
118
|
+
#
|
119
|
+
# ==== Returns
|
120
|
+
# String::
|
121
|
+
# Indicating where to look for the template for the current controller,
|
122
|
+
# context, and content-type.
|
123
|
+
#
|
124
|
+
# ==== Notes
|
125
|
+
# The type is irrelevant for controller-types that don't support
|
126
|
+
# content-type negotiation, so we default to not include it in the
|
127
|
+
# superclass.
|
128
|
+
#
|
129
|
+
# ==== Examples
|
130
|
+
# def _template_location
|
131
|
+
# "#{params[:controller]}.#{params[:action]}.#{content_type}"
|
132
|
+
# end
|
133
|
+
#
|
134
|
+
# This would look for templates at controller.action.mime.type instead
|
135
|
+
# of controller/action.mime.type
|
136
|
+
#---
|
137
|
+
# @public
|
138
|
+
def _template_location(context, type = nil, controller = controller_name)
|
139
|
+
controller ? "#{controller}/#{context}" : context
|
140
|
+
end
|
141
|
+
|
142
|
+
# The location to look for a template - stub method for particular behaviour.
|
143
|
+
#
|
144
|
+
# ==== Parameters
|
145
|
+
# template<String>:: The absolute path to a template - without template extension.
|
146
|
+
# type<~to_s>::
|
147
|
+
# The mime-type of the template that will be rendered. Defaults to nil.
|
148
|
+
#
|
149
|
+
# @public
|
150
|
+
def _absolute_template_location(template, type)
|
151
|
+
template
|
152
|
+
end
|
153
|
+
|
154
|
+
def self._template_root=(root)
|
155
|
+
@_template_root = root
|
156
|
+
_reset_template_roots
|
157
|
+
end
|
158
|
+
|
159
|
+
def self._reset_template_roots
|
160
|
+
self.template_roots = [[self._template_root, :_template_location]]
|
161
|
+
end
|
162
|
+
|
163
|
+
# ==== Returns
|
164
|
+
# roots<Array[Array]>::
|
165
|
+
# Template roots as pairs of template root path and template location
|
166
|
+
# method.
|
167
|
+
def self._template_roots
|
168
|
+
self.template_roots || _reset_template_roots
|
169
|
+
end
|
170
|
+
|
171
|
+
# ==== Parameters
|
172
|
+
# roots<Array[Array]>::
|
173
|
+
# Template roots as pairs of template root path and template location
|
174
|
+
# method.
|
175
|
+
def self._template_roots=(roots)
|
176
|
+
self.template_roots = roots
|
177
|
+
end
|
178
|
+
|
179
|
+
cattr_accessor :_abstract_subclasses, :_template_path_cache
|
180
|
+
#---
|
181
|
+
# We're using abstract_subclasses so that Merb::Controller can have its
|
182
|
+
# own subclasses. We're using a Set so we don't have to worry about
|
183
|
+
# uniqueness.
|
184
|
+
self._abstract_subclasses = Set.new
|
185
|
+
|
186
|
+
# ==== Returns
|
187
|
+
# Set:: The subclasses.
|
188
|
+
def self.subclasses_list() _abstract_subclasses end
|
189
|
+
|
190
|
+
class << self
|
191
|
+
# ==== Parameters
|
192
|
+
# klass<Merb::AbstractController>::
|
193
|
+
# The controller that is being inherited from Merb::AbstractController
|
194
|
+
def inherited(klass)
|
195
|
+
_abstract_subclasses << klass.to_s
|
196
|
+
helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper"
|
197
|
+
Object.make_module helper_module_name
|
198
|
+
klass.class_eval <<-HERE
|
199
|
+
include Object.full_const_get("#{helper_module_name}") rescue nil
|
200
|
+
HERE
|
201
|
+
super
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
attr_accessor :_benchmarks, :_thrown_content
|
206
|
+
|
207
|
+
#---
|
208
|
+
# @semipublic
|
209
|
+
attr_accessor :body
|
210
|
+
|
211
|
+
attr_accessor :action_name
|
212
|
+
|
213
|
+
# ==== Parameters
|
214
|
+
# *args:: The args are ignored.
|
215
|
+
def initialize(*args)
|
216
|
+
@_benchmarks = {}
|
217
|
+
@_caught_content = {}
|
218
|
+
@_template_stack = []
|
219
|
+
end
|
220
|
+
|
221
|
+
# This will dispatch the request, calling setup_session and finalize_session
|
222
|
+
#
|
223
|
+
# ==== Parameters
|
224
|
+
# action<~to_s>::
|
225
|
+
# The action to dispatch to. This will be #send'ed in _call_action.
|
226
|
+
# Defaults to :to_s.
|
227
|
+
#
|
228
|
+
# ==== Raises
|
229
|
+
# MerbControllerError:: Invalid body content caught.
|
230
|
+
def _dispatch(action=:to_s)
|
231
|
+
setup_session
|
232
|
+
self.action_name = action
|
233
|
+
|
234
|
+
caught = catch(:halt) do
|
235
|
+
start = Time.now
|
236
|
+
result = _call_filters(_before_filters)
|
237
|
+
@_benchmarks[:before_filters_time] = Time.now - start if _before_filters
|
238
|
+
result
|
239
|
+
end
|
240
|
+
|
241
|
+
@body = case caught
|
242
|
+
when :filter_chain_completed then _call_action(action_name)
|
243
|
+
when String then caught
|
244
|
+
when nil then _filters_halted
|
245
|
+
when Symbol then __send__(caught)
|
246
|
+
when Proc then caught.call(self)
|
247
|
+
else
|
248
|
+
raise MerbControllerError, "The before filter chain is broken dude. wtf?"
|
249
|
+
end
|
250
|
+
start = Time.now
|
251
|
+
_call_filters(_after_filters)
|
252
|
+
@_benchmarks[:after_filters_time] = Time.now - start if _after_filters
|
253
|
+
finalize_session
|
254
|
+
@body
|
255
|
+
end
|
256
|
+
|
257
|
+
# This method exists to provide an overridable hook for ActionArgs
|
258
|
+
#
|
259
|
+
# ==== Parameters
|
260
|
+
# action<~to_s>:: the action method to dispatch to
|
261
|
+
def _call_action(action)
|
262
|
+
send(action)
|
263
|
+
end
|
264
|
+
|
265
|
+
# ==== Parameters
|
266
|
+
# filter_set<Array[Filter]>::
|
267
|
+
# A set of filters in the form [[:filter, rule], [:filter, rule]]
|
268
|
+
#
|
269
|
+
# ==== Returns
|
270
|
+
# Symbol:: :filter_chain_completed.
|
271
|
+
#
|
272
|
+
# ==== Notes
|
273
|
+
# Filter rules can be Symbols, Strings, or Procs.
|
274
|
+
#
|
275
|
+
# Symbols or Strings::
|
276
|
+
# Call the method represented by the +Symbol+ or +String+.
|
277
|
+
# Procs::
|
278
|
+
# Execute the +Proc+, in the context of the controller (self will be the
|
279
|
+
# controller)
|
280
|
+
def _call_filters(filter_set)
|
281
|
+
(filter_set || []).each do |filter, rule|
|
282
|
+
if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
|
283
|
+
case filter
|
284
|
+
when Symbol, String
|
285
|
+
if rule.key?(:with)
|
286
|
+
args = rule[:with]
|
287
|
+
send(filter, *args)
|
288
|
+
else
|
289
|
+
send(filter)
|
290
|
+
end
|
291
|
+
when Proc then self.instance_eval(&filter)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
return :filter_chain_completed
|
296
|
+
end
|
297
|
+
|
298
|
+
# ==== Parameters
|
299
|
+
# rule<Hash>:: Rules for the filter (see below).
|
300
|
+
# action_name<~to_s>:: The name of the action to be called.
|
301
|
+
#
|
302
|
+
# ==== Options (rule)
|
303
|
+
# :only<Array>::
|
304
|
+
# Optional list of actions to fire. If given, action_name must be a part of
|
305
|
+
# it for this function to return true.
|
306
|
+
# :exclude<Array>::
|
307
|
+
# Optional list of actions not to fire. If given, action_name must not be a
|
308
|
+
# part of it for this function to return true.
|
309
|
+
#
|
310
|
+
# ==== Returns
|
311
|
+
# Boolean:: True if the action should be called.
|
312
|
+
def _call_filter_for_action?(rule, action_name)
|
313
|
+
# Both:
|
314
|
+
# * no :only or the current action is in the :only list
|
315
|
+
# * no :exclude or the current action is not in the :exclude list
|
316
|
+
(!rule.key?(:only) || rule[:only].include?(action_name)) &&
|
317
|
+
(!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
|
318
|
+
end
|
319
|
+
|
320
|
+
# ==== Parameters
|
321
|
+
# rule<Hash>:: Rules for the filter (see below).
|
322
|
+
#
|
323
|
+
# ==== Options (rule)
|
324
|
+
# :if<Array>:: Optional conditions that must be met for the filter to fire.
|
325
|
+
# :unless<Array>::
|
326
|
+
# Optional conditions that must not be met for the filter to fire.
|
327
|
+
#
|
328
|
+
# ==== Returns
|
329
|
+
# Boolean:: True if the conditions are met.
|
330
|
+
def _filter_condition_met?(rule)
|
331
|
+
# Both:
|
332
|
+
# * no :if or the if condition evaluates to true
|
333
|
+
# * no :unless or the unless condition evaluates to false
|
334
|
+
(!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
|
335
|
+
(!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
|
336
|
+
end
|
337
|
+
|
338
|
+
# ==== Parameters
|
339
|
+
# condition<Symbol, Proc>:: The condition to evaluate.
|
340
|
+
#
|
341
|
+
# ==== Raises
|
342
|
+
# ArgumentError:: condition not a Symbol or Proc.
|
343
|
+
#
|
344
|
+
# ==== Returns
|
345
|
+
# Boolean:: True if the condition is met.
|
346
|
+
#
|
347
|
+
# ==== Alternatives
|
348
|
+
# If condition is a symbol, it will be send'ed. If it is a Proc it will be
|
349
|
+
# called directly with self as an argument.
|
350
|
+
def _evaluate_condition(condition)
|
351
|
+
case condition
|
352
|
+
when Symbol : self.send(condition)
|
353
|
+
when Proc : condition.call(self)
|
354
|
+
else
|
355
|
+
raise ArgumentError,
|
356
|
+
'Filter condtions need to be either a Symbol or a Proc'
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
# ==== Parameters
|
361
|
+
# filter<Symbol, Proc>:: The filter to add. Defaults to nil.
|
362
|
+
# opts<Hash>::
|
363
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
364
|
+
# &block:: A block to use as a filter if filter is nil.
|
365
|
+
#
|
366
|
+
# ==== Notes
|
367
|
+
# If the filter already exists, its options will be replaced with opts.
|
368
|
+
def self.after(filter = nil, opts = {}, &block)
|
369
|
+
add_filter(self._after_filters, filter || block, opts)
|
370
|
+
end
|
371
|
+
|
372
|
+
# ==== Parameters
|
373
|
+
# filter<Symbol, Proc>:: The filter to add. Defaults to nil.
|
374
|
+
# opts<Hash>::
|
375
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
376
|
+
# &block:: A block to use as a filter if filter is nil.
|
377
|
+
#
|
378
|
+
# ==== Notes
|
379
|
+
# If the filter already exists, its options will be replaced with opts.
|
380
|
+
def self.before(filter = nil, opts = {}, &block)
|
381
|
+
add_filter(self._before_filters, filter || block, opts)
|
382
|
+
end
|
383
|
+
|
384
|
+
# Skip an after filter that has been previously defined (perhaps in a
|
385
|
+
# superclass)
|
386
|
+
#
|
387
|
+
# ==== Parameters
|
388
|
+
# filter<Symbol>:: A filter name to skip.
|
389
|
+
def self.skip_after(filter)
|
390
|
+
skip_filter(self._after_filters, filter)
|
391
|
+
end
|
392
|
+
|
393
|
+
# Skip a before filter that has been previously defined (perhaps in a
|
394
|
+
# superclass).
|
395
|
+
#
|
396
|
+
# ==== Parameters
|
397
|
+
# filter<Symbol>:: A filter name to skip.
|
398
|
+
def self.skip_before(filter)
|
399
|
+
skip_filter(self._before_filters , filter)
|
400
|
+
end
|
401
|
+
|
402
|
+
#---
|
403
|
+
# Defaults that can be overridden by plugins, other mixins, or subclasses
|
404
|
+
def _filters_halted() "<html><body><h1>Filter Chain Halted!</h1></body></html>" end
|
405
|
+
|
406
|
+
# Method stub for setting up the session. This will be overriden by session
|
407
|
+
# modules.
|
408
|
+
def setup_session() end
|
409
|
+
|
410
|
+
# Method stub for finalizing up the session. This will be overriden by
|
411
|
+
# session modules.
|
412
|
+
def finalize_session() end
|
413
|
+
|
414
|
+
# Stub so content-type support in RenderMixin doesn't throw errors
|
415
|
+
attr_accessor :content_type
|
416
|
+
|
417
|
+
# Handles the template cache (which is used by BootLoader to cache the list
|
418
|
+
# of all templates).
|
419
|
+
#
|
420
|
+
# ==== Parameters
|
421
|
+
# template<String>::
|
422
|
+
# The full path to a template to add to the list of available templates
|
423
|
+
def self.add_path_to_template_cache(template)
|
424
|
+
return false if template.blank? || template.split("/").last.split(".").size != 3
|
425
|
+
key = template.match(/(.*)\.(.*)$/)[1]
|
426
|
+
self._template_path_cache[key] = template
|
427
|
+
end
|
428
|
+
|
429
|
+
# Resets the template_path_cache to an empty hash
|
430
|
+
def self.reset_template_path_cache!
|
431
|
+
self._template_path_cache = {}
|
432
|
+
end
|
433
|
+
|
434
|
+
# ==== Parameters
|
435
|
+
# name<~to_sym, Hash>:: The name of the URL to generate.
|
436
|
+
# rparams<Hash>:: Parameters for the route generation.
|
437
|
+
#
|
438
|
+
# ==== Returns
|
439
|
+
# String:: The generated URL.
|
440
|
+
#
|
441
|
+
# ==== Alternatives
|
442
|
+
# If a hash is used as the first argument, a default route will be
|
443
|
+
# generated based on it and rparams.
|
444
|
+
def url(name, rparams = {}, qparams = {})
|
445
|
+
unless rparams.is_a?(Hash) || qparams.empty?
|
446
|
+
rparams = qparams.merge(:id => rparams)
|
447
|
+
end
|
448
|
+
uri = Merb::Router.generate(name, rparams,
|
449
|
+
{ :controller => controller_name,
|
450
|
+
:action => action_name,
|
451
|
+
:format => params[:format]
|
452
|
+
}
|
453
|
+
)
|
454
|
+
uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
|
455
|
+
uri
|
456
|
+
end
|
457
|
+
alias_method :relative_url, :url
|
458
|
+
|
459
|
+
# ==== Parameters
|
460
|
+
# name<~to_sym, Hash>:: The name of the URL to generate.
|
461
|
+
# rparams<Hash>:: Parameters for the route generation.
|
462
|
+
#
|
463
|
+
# ==== Returns
|
464
|
+
# String:: The generated url with protocol + hostname + URL.
|
465
|
+
#
|
466
|
+
# ==== Alternatives
|
467
|
+
# If a hash is used as the first argument, a default route will be
|
468
|
+
# generated based on it and rparams.
|
469
|
+
def absolute_url(name, rparams={})
|
470
|
+
request.protocol + request.host + url(name, rparams)
|
471
|
+
end
|
472
|
+
|
473
|
+
# Calls the capture method for the selected template engine.
|
474
|
+
#
|
475
|
+
# ==== Parameters
|
476
|
+
# *args:: Arguments to pass to the block.
|
477
|
+
# &block:: The template block to call.
|
478
|
+
#
|
479
|
+
# ==== Returns
|
480
|
+
# String:: The output of the block.
|
481
|
+
def capture(*args, &block)
|
482
|
+
send("capture_#{@_engine}", *args, &block)
|
483
|
+
end
|
484
|
+
|
485
|
+
# Calls the concatenate method for the selected template engine.
|
486
|
+
#
|
487
|
+
# ==== Parameters
|
488
|
+
# str<String>:: The string to concatenate to the buffer.
|
489
|
+
# binding<Binding>:: The binding to use for the buffer.
|
490
|
+
def concat(str, binding)
|
491
|
+
send("concat_#{@_engine}", str, binding)
|
492
|
+
end
|
493
|
+
|
494
|
+
private
|
495
|
+
# ==== Parameters
|
496
|
+
# filters<Array[Filter]>:: The filter list that this should be added to.
|
497
|
+
# filter<Filter>:: A filter that should be added.
|
498
|
+
# opts<Hash>::
|
499
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
500
|
+
#
|
501
|
+
# ==== Raises
|
502
|
+
# ArgumentError::
|
503
|
+
# Both :only and :exclude, or :if and :unless given, if filter is not a
|
504
|
+
# Symbol, String or Proc, or if an unknown option is passed.
|
505
|
+
def self.add_filter(filters, filter, opts={})
|
506
|
+
raise(ArgumentError,
|
507
|
+
"You can specify either :only or :exclude but
|
508
|
+
not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
|
509
|
+
|
510
|
+
raise(ArgumentError,
|
511
|
+
"You can specify either :if or :unless but
|
512
|
+
not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
|
513
|
+
|
514
|
+
opts.each_key do |key| raise(ArgumentError,
|
515
|
+
"You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
|
516
|
+
end
|
517
|
+
|
518
|
+
opts = normalize_filters!(opts)
|
519
|
+
|
520
|
+
case filter
|
521
|
+
when Symbol, Proc, String
|
522
|
+
if existing_filter = filters.find {|f| f.first.to_s[filter.to_s]}
|
523
|
+
existing_filter.last.replace(opts)
|
524
|
+
else
|
525
|
+
filters << [filter, opts]
|
526
|
+
end
|
527
|
+
else
|
528
|
+
raise(ArgumentError,
|
529
|
+
'Filters need to be either a Symbol, String or a Proc'
|
530
|
+
)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
# Skip a filter that was previously added to the filter chain. Useful in
|
535
|
+
# inheritence hierarchies.
|
536
|
+
#
|
537
|
+
# ==== Parameters
|
538
|
+
# filters<Array[Filter]>:: The filter list that this should be removed from.
|
539
|
+
# filter<Filter>:: A filter that should be removed.
|
540
|
+
#
|
541
|
+
# ==== Raises
|
542
|
+
# ArgumentError:: filter not Symbol or String.
|
543
|
+
def self.skip_filter(filters, filter)
|
544
|
+
raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
|
545
|
+
[Symbol, String].include? filter.class
|
546
|
+
|
547
|
+
Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
|
548
|
+
filters.reject! {|f| f.first.to_s[filter.to_s] }
|
549
|
+
end
|
550
|
+
|
551
|
+
# Ensures that the passed in hash values are always arrays.
|
552
|
+
#
|
553
|
+
# ==== Parameters
|
554
|
+
# opts<Hash>:: Options for the filters (see below).
|
555
|
+
#
|
556
|
+
# ==== Options (opts)
|
557
|
+
# :only<Symbol, Array[Symbol]>:: A list of actions.
|
558
|
+
# :exclude<Symbol, Array[Symbol]>:: A list of actions.
|
559
|
+
#
|
560
|
+
# ==== Examples
|
561
|
+
# normalize_filters!(:only => :new) #=> {:only => [:new]}
|
562
|
+
def self.normalize_filters!(opts={})
|
563
|
+
opts[:only] = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
|
564
|
+
opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
|
565
|
+
return opts
|
566
|
+
end
|
567
|
+
|
568
|
+
# Attempts to return the partial local variable corresponding to sym.
|
569
|
+
#
|
570
|
+
# ==== Paramteres
|
571
|
+
# sym<Symbol>:: Method name.
|
572
|
+
# *arg:: Arguments to pass to the method.
|
573
|
+
# &blk:: A block to pass to the method.
|
574
|
+
def method_missing(sym, *args, &blk)
|
575
|
+
return @_merb_partial_locals[sym] if @_merb_partial_locals && @_merb_partial_locals.key?(sym)
|
576
|
+
super
|
577
|
+
end
|
578
|
+
end
|