thorero 0.9.4.4 → 0.9.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
- data/README +21 -0
- data/Rakefile +275 -108
- 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/{extlib → merb-core}/logger.rb +2 -2
- 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 +493 -41
- data/README.txt +0 -3
- data/lib/extlib.rb +0 -32
- data/lib/extlib/assertions.rb +0 -8
- data/lib/extlib/blank.rb +0 -42
- data/lib/extlib/class.rb +0 -175
- data/lib/extlib/hash.rb +0 -410
- data/lib/extlib/hook.rb +0 -366
- data/lib/extlib/inflection.rb +0 -141
- data/lib/extlib/lazy_array.rb +0 -106
- data/lib/extlib/mash.rb +0 -143
- data/lib/extlib/module.rb +0 -37
- data/lib/extlib/object.rb +0 -165
- data/lib/extlib/object_space.rb +0 -13
- data/lib/extlib/pathname.rb +0 -5
- data/lib/extlib/pooling.rb +0 -233
- data/lib/extlib/rubygems.rb +0 -38
- data/lib/extlib/simple_set.rb +0 -39
- data/lib/extlib/string.rb +0 -132
- data/lib/extlib/struct.rb +0 -8
- data/lib/extlib/tasks/release.rb +0 -9
- data/lib/extlib/time.rb +0 -12
- data/lib/extlib/version.rb +0 -3
- data/lib/extlib/virtual_file.rb +0 -10
@@ -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
|