merb-core 0.9.2
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 +285 -0
- data/TODO +0 -0
- data/bin/merb +8 -0
- data/bin/merb-specs +5 -0
- data/docs/bootloading.dox +57 -0
- data/docs/documentation_standards +40 -0
- data/docs/new_render_api +51 -0
- data/lib/merb-core.rb +304 -0
- data/lib/merb-core/autoload.rb +29 -0
- data/lib/merb-core/bootloader.rb +601 -0
- data/lib/merb-core/config.rb +284 -0
- data/lib/merb-core/constants.rb +43 -0
- data/lib/merb-core/controller/abstract_controller.rb +531 -0
- data/lib/merb-core/controller/exceptions.rb +257 -0
- data/lib/merb-core/controller/merb_controller.rb +214 -0
- data/lib/merb-core/controller/mime.rb +88 -0
- data/lib/merb-core/controller/mixins/controller.rb +262 -0
- data/lib/merb-core/controller/mixins/render.rb +324 -0
- data/lib/merb-core/controller/mixins/responder.rb +464 -0
- data/lib/merb-core/controller/template.rb +205 -0
- data/lib/merb-core/core_ext.rb +12 -0
- data/lib/merb-core/core_ext/class.rb +192 -0
- data/lib/merb-core/core_ext/hash.rb +422 -0
- data/lib/merb-core/core_ext/kernel.rb +304 -0
- data/lib/merb-core/core_ext/mash.rb +154 -0
- data/lib/merb-core/core_ext/object.rb +136 -0
- data/lib/merb-core/core_ext/object_space.rb +14 -0
- data/lib/merb-core/core_ext/rubygems.rb +28 -0
- data/lib/merb-core/core_ext/set.rb +41 -0
- data/lib/merb-core/core_ext/string.rb +69 -0
- data/lib/merb-core/dispatch/cookies.rb +92 -0
- data/lib/merb-core/dispatch/dispatcher.rb +233 -0
- data/lib/merb-core/dispatch/exceptions.html.erb +297 -0
- data/lib/merb-core/dispatch/request.rb +560 -0
- data/lib/merb-core/dispatch/router.rb +141 -0
- data/lib/merb-core/dispatch/router/behavior.rb +777 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/route.rb +212 -0
- data/lib/merb-core/dispatch/session.rb +28 -0
- data/lib/merb-core/dispatch/session/cookie.rb +166 -0
- data/lib/merb-core/dispatch/session/memcached.rb +161 -0
- data/lib/merb-core/dispatch/session/memory.rb +234 -0
- data/lib/merb-core/gem_ext/erubis.rb +19 -0
- data/lib/merb-core/logger.rb +230 -0
- data/lib/merb-core/plugins.rb +25 -0
- data/lib/merb-core/rack.rb +15 -0
- data/lib/merb-core/rack/adapter.rb +42 -0
- data/lib/merb-core/rack/adapter/ebb.rb +22 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +24 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +16 -0
- data/lib/merb-core/rack/adapter/irb.rb +108 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +25 -0
- data/lib/merb-core/rack/adapter/runner.rb +27 -0
- data/lib/merb-core/rack/adapter/thin.rb +27 -0
- data/lib/merb-core/rack/adapter/webrick.rb +35 -0
- data/lib/merb-core/rack/application.rb +77 -0
- data/lib/merb-core/rack/handler/mongrel.rb +97 -0
- data/lib/merb-core/server.rb +184 -0
- data/lib/merb-core/test.rb +10 -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 +257 -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 +269 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +293 -0
- data/lib/merb-core/test/run_specs.rb +38 -0
- data/lib/merb-core/test/tasks/spectasks.rb +39 -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/vendor/facets.rb +2 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
- data/lib/merb-core/vendor/facets/inflect.rb +211 -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 +139 -0
- data/spec/private/config/environment_spec.rb +13 -0
- data/spec/private/config/spec_helper.rb +1 -0
- data/spec/private/core_ext/hash_spec.rb +506 -0
- data/spec/private/core_ext/kernel_spec.rb +46 -0
- data/spec/private/core_ext/object_spec.rb +39 -0
- data/spec/private/core_ext/set_spec.rb +26 -0
- data/spec/private/core_ext/string_spec.rb +9 -0
- data/spec/private/dispatch/cookies_spec.rb +107 -0
- data/spec/private/dispatch/dispatch_spec.rb +26 -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/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 +1 -0
- data/spec/private/dispatch/fixture/config/router.rb +35 -0
- data/spec/private/dispatch/fixture/log/development.log +1 -0
- data/spec/private/dispatch/fixture/log/merb.4000.pid +1 -0
- data/spec/private/dispatch/fixture/log/merb_test.log +2040 -0
- data/spec/private/dispatch/fixture/log/production.log +1 -0
- data/spec/private/dispatch/fixture/merb.4000.pid +1 -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/spec_helper.rb +1 -0
- data/spec/private/plugins/plugin_spec.rb +81 -0
- data/spec/private/rack/application_spec.rb +43 -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/display.rb +54 -0
- data/spec/public/abstract_controller/controllers/filters.rb +167 -0
- data/spec/public/abstract_controller/controllers/helpers.rb +31 -0
- data/spec/public/abstract_controller/controllers/partial.rb +106 -0
- data/spec/public/abstract_controller/controllers/render.rb +86 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture/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/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_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_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 +80 -0
- data/spec/public/abstract_controller/helper_spec.rb +13 -0
- data/spec/public/abstract_controller/partial_spec.rb +53 -0
- data/spec/public/abstract_controller/render_spec.rb +70 -0
- data/spec/public/abstract_controller/spec_helper.rb +27 -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/base_spec.rb +31 -0
- data/spec/public/controller/controllers/base.rb +41 -0
- data/spec/public/controller/controllers/display.rb +40 -0
- data/spec/public/controller/controllers/responder.rb +67 -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/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/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 +34 -0
- data/spec/public/controller/log/merb.4000.pid +1 -0
- data/spec/public/controller/responder_spec.rb +95 -0
- data/spec/public/controller/spec_helper.rb +9 -0
- data/spec/public/controller/url_spec.rb +152 -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.4000.pid +1 -0
- data/spec/public/directory_structure/directory/log/merb_test.log +265 -0
- data/spec/public/directory_structure/directory/merb.4000.pid +1 -0
- data/spec/public/directory_structure/directory_spec.rb +44 -0
- data/spec/public/logger/logger_spec.rb +175 -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.4000.pid +1 -0
- data/spec/public/reloading/directory/log/merb_test.log +59 -0
- data/spec/public/reloading/directory/merb.4000.pid +1 -0
- data/spec/public/reloading/reload_spec.rb +80 -0
- data/spec/public/request/multipart_spec.rb +15 -0
- data/spec/public/request/request_spec.rb +207 -0
- data/spec/public/router/default_spec.rb +21 -0
- data/spec/public/router/deferred_spec.rb +22 -0
- data/spec/public/router/namespace_spec.rb +113 -0
- data/spec/public/router/nested_resources_spec.rb +34 -0
- data/spec/public/router/resource_spec.rb +45 -0
- data/spec/public/router/resources_spec.rb +57 -0
- data/spec/public/router/spec_helper.rb +72 -0
- data/spec/public/router/special_spec.rb +44 -0
- data/spec/public/router/string_spec.rb +61 -0
- data/spec/public/template/template_spec.rb +92 -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 +378 -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 +30 -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 +153 -0
- data/spec/public/test/route_helper_spec.rb +54 -0
- data/spec/public/test/route_matchers_spec.rb +133 -0
- data/spec/public/test/view_helper_spec.rb +96 -0
- data/spec/public/test/view_matchers_spec.rb +107 -0
- data/spec/spec_helper.rb +71 -0
- metadata +488 -0
@@ -0,0 +1,284 @@
|
|
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
|
+
:disabled_components => []
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Yields the configuration.
|
29
|
+
#
|
30
|
+
# ==== Block parameters
|
31
|
+
# c<Hash>:: The configuration parameters.
|
32
|
+
#
|
33
|
+
# ==== Examples
|
34
|
+
# Merb::Config.use do |config|
|
35
|
+
# config[:exception_details] = false
|
36
|
+
# end
|
37
|
+
def use
|
38
|
+
@configuration ||= {}
|
39
|
+
yield @configuration
|
40
|
+
end
|
41
|
+
|
42
|
+
# ==== Parameters
|
43
|
+
# key<Object>:: The key to check.
|
44
|
+
#
|
45
|
+
# ==== Returns
|
46
|
+
# Boolean:: True if the key exists in the config.
|
47
|
+
def key?(key)
|
48
|
+
@configuration.key?(key)
|
49
|
+
end
|
50
|
+
|
51
|
+
# ==== Parameters
|
52
|
+
# key<Object>:: The key to retrieve the parameter for.
|
53
|
+
#
|
54
|
+
# ==== Returns
|
55
|
+
# Object:: The value of the configuration parameter.
|
56
|
+
def [](key)
|
57
|
+
(@configuration||={})[key]
|
58
|
+
end
|
59
|
+
|
60
|
+
# ==== Parameters
|
61
|
+
# key<Object>:: The key to set the parameter for.
|
62
|
+
# val<Object>:: The value of the parameter.
|
63
|
+
def []=(key,val)
|
64
|
+
@configuration[key] = val
|
65
|
+
end
|
66
|
+
|
67
|
+
# ==== Parameters
|
68
|
+
# key<Object>:: The key of the parameter to delete.
|
69
|
+
def delete(key)
|
70
|
+
@configuration.delete(key)
|
71
|
+
end
|
72
|
+
|
73
|
+
# ==== Parameters
|
74
|
+
# key<Object>:: The key to retrieve the parameter for.
|
75
|
+
# default<Object>::
|
76
|
+
# The default value to return if the parameter is not set.
|
77
|
+
#
|
78
|
+
# ==== Returns
|
79
|
+
# Object:: The value of the configuration parameter or the default.
|
80
|
+
def fetch(key, default)
|
81
|
+
@configuration.fetch(key, default)
|
82
|
+
end
|
83
|
+
|
84
|
+
# ==== Returns
|
85
|
+
# Hash:: The config as a hash.
|
86
|
+
def to_hash
|
87
|
+
@configuration
|
88
|
+
end
|
89
|
+
|
90
|
+
# ==== Returns
|
91
|
+
# String:: The config as YAML.
|
92
|
+
def to_yaml
|
93
|
+
@configuration.to_yaml
|
94
|
+
end
|
95
|
+
|
96
|
+
# Sets up the configuration by storing the given settings.
|
97
|
+
#
|
98
|
+
# ==== Parameters
|
99
|
+
# settings<Hash>::
|
100
|
+
# Configuration settings to use. These are merged with the defaults.
|
101
|
+
def setup(settings = {})
|
102
|
+
@configuration = defaults.merge(settings)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Parses the command line arguments and stores them in the config.
|
106
|
+
#
|
107
|
+
# ==== Parameters
|
108
|
+
# argv<String>:: The command line arguments. Defaults to +ARGV+.
|
109
|
+
def parse_args(argv = ARGV)
|
110
|
+
@configuration ||= {}
|
111
|
+
# Our primary configuration hash for the length of this method
|
112
|
+
options = {}
|
113
|
+
|
114
|
+
# Environment variables always win
|
115
|
+
options[:environment] = ENV["MERB_ENV"] if ENV["MERB_ENV"]
|
116
|
+
|
117
|
+
# Build a parser for the command line arguments
|
118
|
+
opts = OptionParser.new do |opts|
|
119
|
+
opts.version = Merb::VERSION
|
120
|
+
opts.release = Merb::RELEASE
|
121
|
+
|
122
|
+
opts.banner = "Usage: merb [uGdcIpPhmailLerkKX] [argument]"
|
123
|
+
opts.define_head "Merb Mongrel+ Erb. Lightweight replacement for ActionPack."
|
124
|
+
opts.separator '*'*80
|
125
|
+
opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
|
126
|
+
opts.separator '*'*80
|
127
|
+
|
128
|
+
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|
|
129
|
+
options[:user] = user
|
130
|
+
end
|
131
|
+
|
132
|
+
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|
|
133
|
+
options[:group] = group
|
134
|
+
end
|
135
|
+
|
136
|
+
opts.on("-d", "--daemonize", "This will run a single merb in the background.") do |daemon|
|
137
|
+
options[:daemonize] = true
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run.") do |nodes|
|
141
|
+
options[:cluster] = nodes
|
142
|
+
end
|
143
|
+
|
144
|
+
opts.on("-I", "--init-file FILE", "Name of the file to load first") do |init_file|
|
145
|
+
options[:init_file] = init_file
|
146
|
+
end
|
147
|
+
|
148
|
+
opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
|
149
|
+
options[:port] = port
|
150
|
+
end
|
151
|
+
|
152
|
+
opts.on("-P", "--pid PIDFILE", "PID file, defaults to [Merb.root]/log/merb.[port_number].pid") do |pid_file|
|
153
|
+
options[:pid_file] = pid_file
|
154
|
+
end
|
155
|
+
|
156
|
+
opts.on("-h", "--host HOSTNAME", "Host to bind to (default is 0.0.0.0).") do |host|
|
157
|
+
options[:host] = host
|
158
|
+
end
|
159
|
+
|
160
|
+
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|
|
161
|
+
options[:merb_root] = File.expand_path(root)
|
162
|
+
end
|
163
|
+
|
164
|
+
opts.on("-a", "--adapter mongrel", "The rack adapter to use to run merb[mongrel, emongrel, thin, fastcgi, webrick, runner, irb]") do |adapter|
|
165
|
+
options[:adapter] = adapter
|
166
|
+
end
|
167
|
+
|
168
|
+
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|
|
169
|
+
options[:adapter] = 'irb'
|
170
|
+
end
|
171
|
+
|
172
|
+
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|
|
173
|
+
options[:sandbox] = true
|
174
|
+
end
|
175
|
+
|
176
|
+
opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of these options: debug < info < warn < error < fatal") do |log_level|
|
177
|
+
options[:log_level] = log_level.to_sym
|
178
|
+
end
|
179
|
+
|
180
|
+
opts.on("-L", "--log LOGFILE", "A string representing the logfile to use.") do |log_file|
|
181
|
+
options[:log_file] = log_file
|
182
|
+
end
|
183
|
+
|
184
|
+
opts.on("-e", "--environment STRING", "Run merb in the correct mode(development, production, testing)") do |env|
|
185
|
+
options[:environment] = env
|
186
|
+
end
|
187
|
+
|
188
|
+
opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
|
189
|
+
"Command-line option to run scripts and/or code in the merb app.") do |code_or_file|
|
190
|
+
options[:runner_code] = code_or_file
|
191
|
+
options[:adapter] = 'runner'
|
192
|
+
end
|
193
|
+
|
194
|
+
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|
|
195
|
+
@configuration = defaults.merge(options)
|
196
|
+
Merb::Server.kill(ports, 1)
|
197
|
+
end
|
198
|
+
|
199
|
+
opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. Use merb -k all to kill all merbs.") do |port|
|
200
|
+
@configuration = defaults.merge(options)
|
201
|
+
Merb::Server.kill(port, 9)
|
202
|
+
end
|
203
|
+
|
204
|
+
opts.on("-X", "--mutex on/off", "This flag is for turning the mutex lock on and off.") do |mutex|
|
205
|
+
if mutex == "off"
|
206
|
+
options[:use_mutex] = false
|
207
|
+
else
|
208
|
+
options[:use_mutex] = true
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
opts.on("-D", "--debugger", "Run merb using rDebug.") do
|
213
|
+
begin
|
214
|
+
require "ruby-debug"
|
215
|
+
Debugger.start
|
216
|
+
Debugger.settings[:autoeval] = true if Debugger.respond_to?(:settings)
|
217
|
+
puts "Debugger enabled"
|
218
|
+
rescue LoadError
|
219
|
+
puts "You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug'"
|
220
|
+
exit
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
opts.on("-?", "-H", "--help", "Show this help message") do
|
225
|
+
puts opts
|
226
|
+
exit
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
# Parse what we have on the command line
|
231
|
+
opts.parse!(argv)
|
232
|
+
Merb::Config.setup(options)
|
233
|
+
end
|
234
|
+
|
235
|
+
attr_accessor :configuration #:nodoc:
|
236
|
+
|
237
|
+
# Set configuration parameters from a code block, where each method
|
238
|
+
# evaluates to a config parameter.
|
239
|
+
#
|
240
|
+
# ==== Parameters
|
241
|
+
# &block:: Configuration parameter block.
|
242
|
+
#
|
243
|
+
# ==== Examples
|
244
|
+
# # Set environment and log level.
|
245
|
+
# Merb::Config.configure do
|
246
|
+
# environment "development"
|
247
|
+
# log_level "debug"
|
248
|
+
# end
|
249
|
+
def configure(&block)
|
250
|
+
ConfigBlock.new(self, &block) if block_given?
|
251
|
+
end
|
252
|
+
|
253
|
+
# Allows retrieval of single key config values via Merb.config.<key>
|
254
|
+
# Allows single key assignment via Merb.config.<key> = ...
|
255
|
+
#
|
256
|
+
# ==== Parameters
|
257
|
+
# method<~to_s>:: Method name as hash key value.
|
258
|
+
# *args:: Value to set the configuration parameter to.
|
259
|
+
def method_missing(method, *args) #:nodoc:
|
260
|
+
if method.to_s[-1,1] == '='
|
261
|
+
@configuration[method.to_s.tr('=','').to_sym] = *args
|
262
|
+
else
|
263
|
+
@configuration[method]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
end # class << self
|
268
|
+
|
269
|
+
class ConfigBlock #:nodoc:
|
270
|
+
|
271
|
+
def initialize(klass, &block) #:nodoc:
|
272
|
+
@klass = klass
|
273
|
+
instance_eval(&block)
|
274
|
+
end
|
275
|
+
|
276
|
+
def method_missing(method, *args) #:nodoc:
|
277
|
+
@klass[method] = *args
|
278
|
+
end
|
279
|
+
|
280
|
+
end # class Configurator
|
281
|
+
|
282
|
+
end # Config
|
283
|
+
|
284
|
+
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,531 @@
|
|
1
|
+
# Note that the over-use of "_" in Controller methods is to avoid collisions
|
2
|
+
# with helpers, which will be pulled directly into controllers from now on.
|
3
|
+
#
|
4
|
+
# ==== Filters
|
5
|
+
# #before is a class method that allows you to specify before filters in
|
6
|
+
# your controllers. Filters can either be a symbol or string that
|
7
|
+
# corresponds to a method name to call, or a proc object. if it is a method
|
8
|
+
# name that method will be called and if it is a proc it will be called
|
9
|
+
# with an argument of self where self is the current controller object.
|
10
|
+
# When you use a proc as a filter it needs to take one parameter.
|
11
|
+
#
|
12
|
+
# #after is identical, but the filters are run after the action is invoked.
|
13
|
+
#
|
14
|
+
# ==== Examples
|
15
|
+
# before :some_filter
|
16
|
+
# before :authenticate, :exclude => [:login, :signup]
|
17
|
+
# before Proc.new {|c| c.some_method }, :only => :foo
|
18
|
+
# before :authorize, :unless => logged_in?
|
19
|
+
#
|
20
|
+
# You can use either :only => :actionname or :exclude => [:this, :that]
|
21
|
+
# but not both at once. :only will only run before the listed actions
|
22
|
+
# and :exclude will run for every action that is not listed.
|
23
|
+
#
|
24
|
+
# Merb's before filter chain is very flexible. To halt the filter chain you
|
25
|
+
# use throw :halt. If throw is called with only one argument of :halt the
|
26
|
+
# return of the method filters_halted will be what is rendered to the view.
|
27
|
+
# You can overide filters_halted in your own controllers to control what it
|
28
|
+
# outputs. But the throw construct is much more powerful then just that.
|
29
|
+
# throw :halt can also take a second argument. Here is what that second arg
|
30
|
+
# can be and the behavior each type can have:
|
31
|
+
#
|
32
|
+
# * +String+:
|
33
|
+
# when the second arg is a string then that string will be what
|
34
|
+
# is rendered to the browser. Since merb's render method returns
|
35
|
+
# a string you can render a template or just use a plain string:
|
36
|
+
#
|
37
|
+
# throw :halt, "You don't have permissions to do that!"
|
38
|
+
# throw :halt, render(:action => :access_denied)
|
39
|
+
#
|
40
|
+
# * +Symbol+:
|
41
|
+
# If the second arg is a symbol then the method named after that
|
42
|
+
# symbol will be called
|
43
|
+
#
|
44
|
+
# throw :halt, :must_click_disclaimer
|
45
|
+
#
|
46
|
+
# * +Proc+:
|
47
|
+
#
|
48
|
+
# If the second arg is a Proc, it will be called and its return
|
49
|
+
# value will be what is rendered to the browser:
|
50
|
+
#
|
51
|
+
# throw :halt, proc {|c| c.access_denied }
|
52
|
+
# throw :halt, proc {|c| Tidy.new(c.index) }
|
53
|
+
#
|
54
|
+
# ==== Filter Options (.before, .after, .add_filter, .if, .unless)
|
55
|
+
# :only<Symbol, Array[Symbol]>::
|
56
|
+
# A list of actions that this filter should apply to
|
57
|
+
#
|
58
|
+
# :exclude<Symbol, Array[Symbol]::
|
59
|
+
# A list of actions that this filter should *not* apply to
|
60
|
+
#
|
61
|
+
# :if<Symbol, Proc>::
|
62
|
+
# Only apply the filter if the method named after the symbol or calling the proc evaluates to true
|
63
|
+
#
|
64
|
+
# :unless<Symbol, Proc>::
|
65
|
+
# Only apply the filter if the method named after the symbol or calling the proc evaluates to false
|
66
|
+
#
|
67
|
+
# ==== Types (shortcuts for use in this file)
|
68
|
+
# Filter:: <Array[Symbol, (Symbol, String, Proc)]>
|
69
|
+
class Merb::AbstractController
|
70
|
+
include Merb::RenderMixin
|
71
|
+
include Merb::InlineTemplates
|
72
|
+
|
73
|
+
class_inheritable_accessor :_before_filters, :_after_filters, :_layout, :_template_root
|
74
|
+
|
75
|
+
# ==== Returns
|
76
|
+
# String:: The controller name in path form, e.g. "admin/items".
|
77
|
+
#---
|
78
|
+
# @public
|
79
|
+
def self.controller_name() @controller_name ||= self.name.to_const_path end
|
80
|
+
|
81
|
+
# ==== Returns
|
82
|
+
# String:: The controller name in path form, e.g. "admin/items".
|
83
|
+
def controller_name() self.class.controller_name end
|
84
|
+
|
85
|
+
self._before_filters, self._after_filters = [], []
|
86
|
+
|
87
|
+
# This is called after the controller is instantiated to figure out where to
|
88
|
+
# for templates under the _template_root. Override this to define a new
|
89
|
+
# structure for your app.
|
90
|
+
#
|
91
|
+
# ==== Parameters
|
92
|
+
# action<~to_s>:: The controller action.
|
93
|
+
# type<~to_s>:: The content type. Defaults to nil.
|
94
|
+
# controller<~to_s>::
|
95
|
+
# The name of the controller. Defaults to controller_name.
|
96
|
+
#
|
97
|
+
#
|
98
|
+
# ==== Returns
|
99
|
+
# String::
|
100
|
+
# Indicating where to look for the template for the current controller,
|
101
|
+
# action, and content-type.
|
102
|
+
#
|
103
|
+
# ==== Note
|
104
|
+
# The type is irrelevant for controller-types that don't support
|
105
|
+
# content-type negotiation, so we default to not include it in the
|
106
|
+
# superclass.
|
107
|
+
#
|
108
|
+
# ==== Examples
|
109
|
+
# def _template_location
|
110
|
+
# "#{params[:controller]}.#{params[:action]}.#{content_type}"
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# This would look for templates at controller.action.mime.type instead
|
114
|
+
# of controller/action.mime.type
|
115
|
+
#---
|
116
|
+
# @public
|
117
|
+
def _template_location(action, type = nil, controller = controller_name)
|
118
|
+
"#{controller}/#{action}"
|
119
|
+
end
|
120
|
+
|
121
|
+
# ==== Returns
|
122
|
+
# roots<Array[Array]>::
|
123
|
+
# Template roots as pairs of template root path and template location
|
124
|
+
# method.
|
125
|
+
def self._template_roots
|
126
|
+
read_inheritable_attribute(:template_roots) ||
|
127
|
+
write_inheritable_attribute(:template_roots, [[self._template_root, :_template_location]])
|
128
|
+
end
|
129
|
+
|
130
|
+
# ==== Parameters
|
131
|
+
# roots<Array[Array]>::
|
132
|
+
# Template roots as pairs of template root path and template location
|
133
|
+
# method.
|
134
|
+
def self._template_roots=(roots)
|
135
|
+
write_inheritable_attribute(:template_roots, roots)
|
136
|
+
end
|
137
|
+
|
138
|
+
cattr_accessor :_abstract_subclasses, :_template_path_cache
|
139
|
+
#---
|
140
|
+
# We're using abstract_subclasses so that Merb::Controller can have its
|
141
|
+
# own subclasses. We're using a Set so we don't have to worry about
|
142
|
+
# uniqueness.
|
143
|
+
self._abstract_subclasses = Set.new
|
144
|
+
|
145
|
+
# ==== Returns
|
146
|
+
# Set:: The subclasses.
|
147
|
+
def self.subclasses_list() _abstract_subclasses end
|
148
|
+
|
149
|
+
class << self
|
150
|
+
# ==== Parameters
|
151
|
+
# klass<Merb::AbstractController>::
|
152
|
+
# The controller that is being inherited from Merb::AbstractController
|
153
|
+
def inherited(klass)
|
154
|
+
_abstract_subclasses << klass.to_s
|
155
|
+
Object.make_module "Merb::#{klass}Helper" unless klass.to_s =~ /^Merb::/
|
156
|
+
klass.class_eval <<-HERE
|
157
|
+
include Object.full_const_get("Merb::#{klass}Helper") rescue nil
|
158
|
+
HERE
|
159
|
+
super
|
160
|
+
end
|
161
|
+
|
162
|
+
# ==== Parameters
|
163
|
+
# layout<~to_s>:: The layout that should be used for this class
|
164
|
+
#
|
165
|
+
# ==== Returns
|
166
|
+
# ~to_s:: The layout that was passed in
|
167
|
+
def layout(layout)
|
168
|
+
self._layout = layout
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
attr_accessor :_benchmarks, :_thrown_content
|
173
|
+
|
174
|
+
#---
|
175
|
+
# @semipublic
|
176
|
+
attr_accessor :body
|
177
|
+
|
178
|
+
attr_accessor :action_name
|
179
|
+
|
180
|
+
# ==== Parameters
|
181
|
+
# *args:: The args are ignored.
|
182
|
+
def initialize(*args)
|
183
|
+
@_benchmarks = {}
|
184
|
+
@_caught_content = {}
|
185
|
+
@_template_stack = []
|
186
|
+
end
|
187
|
+
|
188
|
+
# This will dispatch the request, calling setup_session and finalize_session
|
189
|
+
#
|
190
|
+
# ==== Parameters
|
191
|
+
# action<~to_s>::
|
192
|
+
# The action to dispatch to. This will be #send'ed in _call_action.
|
193
|
+
# Defaults to :to_s.
|
194
|
+
#
|
195
|
+
# ==== Raises
|
196
|
+
# MerbControllerError:: Invalid body content caught.
|
197
|
+
def _dispatch(action=:to_s)
|
198
|
+
setup_session
|
199
|
+
self.action_name = action
|
200
|
+
|
201
|
+
caught = catch(:halt) do
|
202
|
+
start = Time.now
|
203
|
+
result = _call_filters(_before_filters)
|
204
|
+
@_benchmarks[:before_filters_time] = Time.now - start if _before_filters
|
205
|
+
result
|
206
|
+
end
|
207
|
+
|
208
|
+
@body = case caught
|
209
|
+
when :filter_chain_completed then _call_action(action_name)
|
210
|
+
when String then caught
|
211
|
+
when nil then _filters_halted
|
212
|
+
when Symbol then __send__(caught)
|
213
|
+
when Proc then caught.call(self)
|
214
|
+
else
|
215
|
+
raise MerbControllerError, "The before filter chain is broken dude. wtf?"
|
216
|
+
end
|
217
|
+
start = Time.now
|
218
|
+
_call_filters(_after_filters)
|
219
|
+
@_benchmarks[:after_filters_time] = Time.now - start if _after_filters
|
220
|
+
finalize_session
|
221
|
+
end
|
222
|
+
|
223
|
+
# This method exists to provide an overridable hook for ActionArgs
|
224
|
+
#
|
225
|
+
# ==== Parameters
|
226
|
+
# action<~to_s>:: the action method to dispatch to
|
227
|
+
def _call_action(action)
|
228
|
+
send(action)
|
229
|
+
end
|
230
|
+
|
231
|
+
# ==== Parameters
|
232
|
+
# filter_set<Array[Filter]>::
|
233
|
+
# A set of filters in the form [[:filter, rule], [:filter, rule]]
|
234
|
+
#
|
235
|
+
# ==== Returns
|
236
|
+
# Symbol:: :filter_chain_completed.
|
237
|
+
#
|
238
|
+
# ==== Notes
|
239
|
+
# Filter rules can be Symbols, Strings, or Procs.
|
240
|
+
#
|
241
|
+
# Symbols or Strings::
|
242
|
+
# Call the method represented by the +Symbol+ or +String+.
|
243
|
+
# Procs::
|
244
|
+
# Execute the +Proc+, in the context of the controller (self will be the
|
245
|
+
# controller)
|
246
|
+
def _call_filters(filter_set)
|
247
|
+
(filter_set || []).each do |filter, rule|
|
248
|
+
if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
|
249
|
+
case filter
|
250
|
+
when Symbol, String then send(filter)
|
251
|
+
when Proc then self.instance_eval(&filter)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
return :filter_chain_completed
|
256
|
+
end
|
257
|
+
|
258
|
+
# ==== Parameters
|
259
|
+
# rule<Hash>:: Rules for the filter (see below).
|
260
|
+
# action_name<~to_s>:: The name of the action to be called.
|
261
|
+
#
|
262
|
+
# ==== Options (rule)
|
263
|
+
# :only<Array>::
|
264
|
+
# Optional list of actions to fire. If given, action_name must be a part of
|
265
|
+
# it for this function to return true.
|
266
|
+
# :exclude<Array>::
|
267
|
+
# Optional list of actions not to fire. If given, action_name must not be a
|
268
|
+
# part of it for this function to return true.
|
269
|
+
#
|
270
|
+
# ==== Returns
|
271
|
+
# Boolean:: True if the action should be called.
|
272
|
+
def _call_filter_for_action?(rule, action_name)
|
273
|
+
# Both:
|
274
|
+
# * no :only or the current action is in the :only list
|
275
|
+
# * no :exclude or the current action is not in the :exclude list
|
276
|
+
(!rule.key?(:only) || rule[:only].include?(action_name)) &&
|
277
|
+
(!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
|
278
|
+
end
|
279
|
+
|
280
|
+
# ==== Parameters
|
281
|
+
# rule<Hash>:: Rules for the filter (see below).
|
282
|
+
#
|
283
|
+
# ==== Options (rule)
|
284
|
+
# :if<Array>:: Optional conditions that must be met for the filter to fire.
|
285
|
+
# :unless<Array>::
|
286
|
+
# Optional conditions that must not be met for the filter to fire.
|
287
|
+
#
|
288
|
+
# ==== Returns
|
289
|
+
# Boolean:: True if the conditions are met.
|
290
|
+
def _filter_condition_met?(rule)
|
291
|
+
# Both:
|
292
|
+
# * no :if or the if condition evaluates to true
|
293
|
+
# * no :unless or the unless condition evaluates to false
|
294
|
+
(!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
|
295
|
+
(!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
|
296
|
+
end
|
297
|
+
|
298
|
+
# ==== Parameters
|
299
|
+
# condition<Symbol, Proc>:: The condition to evaluate.
|
300
|
+
#
|
301
|
+
# ==== Raises
|
302
|
+
# ArgumentError:: condition not a Symbol or Proc.
|
303
|
+
#
|
304
|
+
# ==== Returns
|
305
|
+
# Boolean:: True if the condition is met.
|
306
|
+
#
|
307
|
+
# ==== Alternatives
|
308
|
+
# If condition is a symbol, it will be send'ed. If it is a Proc it will be
|
309
|
+
# called directly with self as an argument.
|
310
|
+
def _evaluate_condition(condition)
|
311
|
+
case condition
|
312
|
+
when Symbol : self.send(condition)
|
313
|
+
when Proc : condition.call(self)
|
314
|
+
else
|
315
|
+
raise ArgumentError,
|
316
|
+
'Filter condtions need to be either a Symbol or a Proc'
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
# ==== Parameters
|
321
|
+
# filter<Symbol, Proc>:: The filter to add. Defaults to nil.
|
322
|
+
# opts<Hash>::
|
323
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
324
|
+
# &block:: Currently ignored.
|
325
|
+
#
|
326
|
+
# ==== Note
|
327
|
+
# If the filter already exists, its options will be replaced with opts.
|
328
|
+
def self.after(filter = nil, opts = {}, &block)
|
329
|
+
add_filter(self._after_filters, filter, opts)
|
330
|
+
end
|
331
|
+
|
332
|
+
# ==== Parameters
|
333
|
+
# filter<Symbol, Proc>:: The filter to add. Defaults to nil.
|
334
|
+
# opts<Hash>::
|
335
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
336
|
+
# &block:: A block to use as a filter if filter is nil.
|
337
|
+
#
|
338
|
+
# ==== Note
|
339
|
+
# If the filter already exists, its options will be replaced with opts.
|
340
|
+
def self.before(filter = nil, opts = {}, &block)
|
341
|
+
add_filter(self._before_filters, filter || block, opts)
|
342
|
+
end
|
343
|
+
|
344
|
+
# Skip an after filter that has been previously defined (perhaps in a
|
345
|
+
# superclass)
|
346
|
+
#
|
347
|
+
# ==== Parameters
|
348
|
+
# filter<Symbol>:: A filter name to skip.
|
349
|
+
def self.skip_after(filter)
|
350
|
+
skip_filter(self._after_filters, filter)
|
351
|
+
end
|
352
|
+
|
353
|
+
# Skip a before filter that has been previously defined (perhaps in a
|
354
|
+
# superclass).
|
355
|
+
#
|
356
|
+
# ==== Parameters
|
357
|
+
# filter<Symbol>:: A filter name to skip.
|
358
|
+
def self.skip_before(filter)
|
359
|
+
skip_filter(self._before_filters , filter)
|
360
|
+
end
|
361
|
+
|
362
|
+
#---
|
363
|
+
# Defaults that can be overridden by plugins, other mixins, or subclasses
|
364
|
+
def _filters_halted() "<html><body><h1>Filter Chain Halted!</h1></body></html>" end
|
365
|
+
|
366
|
+
# Method stub for setting up the session. This will be overriden by session
|
367
|
+
# modules.
|
368
|
+
def setup_session() end
|
369
|
+
|
370
|
+
# Method stub for finalizing up the session. This will be overriden by
|
371
|
+
# session modules.
|
372
|
+
def finalize_session() end
|
373
|
+
|
374
|
+
# Stub so content-type support in RenderMixin doesn't throw errors
|
375
|
+
attr_accessor :content_type
|
376
|
+
|
377
|
+
# Handles the template cache (which is used by BootLoader to cache the list
|
378
|
+
# of all templates).
|
379
|
+
#
|
380
|
+
# ==== Parameters
|
381
|
+
# template<String>::
|
382
|
+
# The full path to a template to add to the list of available templates
|
383
|
+
def self.add_path_to_template_cache(template)
|
384
|
+
return false if template.blank? || template.split("/").last.split(".").size != 3
|
385
|
+
key = template.match(/(.*)\.(.*)$/)[1]
|
386
|
+
self._template_path_cache[key] = template
|
387
|
+
end
|
388
|
+
|
389
|
+
# Resets the template_path_cache to an empty hash
|
390
|
+
def self.reset_template_path_cache!
|
391
|
+
self._template_path_cache = {}
|
392
|
+
end
|
393
|
+
|
394
|
+
# ==== Parameters
|
395
|
+
# name<~to_sym, Hash>:: The name of the URL to generate.
|
396
|
+
# rparams<Hash>:: Parameters for the route generation.
|
397
|
+
#
|
398
|
+
# ==== Returns
|
399
|
+
# String:: The generated URL.
|
400
|
+
#
|
401
|
+
# ==== Alternatives
|
402
|
+
# If a hash is used as the first argument, a default route will be
|
403
|
+
# generated based on it and rparams.
|
404
|
+
def url(name, rparams={})
|
405
|
+
uri = Merb::Router.generate(name, rparams,
|
406
|
+
{ :controller => controller_name,
|
407
|
+
:action => action_name,
|
408
|
+
:format => params[:format]
|
409
|
+
}
|
410
|
+
)
|
411
|
+
uri = Merb::Config[:path_prefix] + uri if Merb::Config[:path_prefix]
|
412
|
+
uri
|
413
|
+
end
|
414
|
+
alias_method :relative_url, :url
|
415
|
+
|
416
|
+
# ==== Parameters
|
417
|
+
# name<~to_sym, Hash>:: The name of the URL to generate.
|
418
|
+
# rparams<Hash>:: Parameters for the route generation.
|
419
|
+
#
|
420
|
+
# ==== Returns
|
421
|
+
# String:: The generated url with protocol + hostname + URL.
|
422
|
+
#
|
423
|
+
# ==== Alternatives
|
424
|
+
# If a hash is used as the first argument, a default route will be
|
425
|
+
# generated based on it and rparams.
|
426
|
+
def absolute_url(name, rparams={})
|
427
|
+
request.protocol + request.host + url(name, rparams)
|
428
|
+
end
|
429
|
+
|
430
|
+
private
|
431
|
+
# ==== Parameters
|
432
|
+
# filters<Array[Filter]>:: The filter list that this should be added to.
|
433
|
+
# filter<Filter>:: A filter that should be added.
|
434
|
+
# opts<Hash>::
|
435
|
+
# Filter options (see class documentation under <tt>Filter Options</tt>).
|
436
|
+
#
|
437
|
+
# ==== Raises
|
438
|
+
# ArgumentError::
|
439
|
+
# Both :only and :exclude, or :if and :unless given, or filter is not a
|
440
|
+
# Symbol, String or Proc.
|
441
|
+
def self.add_filter(filters, filter, opts={})
|
442
|
+
raise(ArgumentError,
|
443
|
+
"You can specify either :only or :exclude but
|
444
|
+
not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
|
445
|
+
|
446
|
+
raise(ArgumentError,
|
447
|
+
"You can specify either :if or :unless but
|
448
|
+
not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
|
449
|
+
|
450
|
+
opts = normalize_filters!(opts)
|
451
|
+
|
452
|
+
case filter
|
453
|
+
when Symbol, Proc, String
|
454
|
+
if existing_filter = filters.find {|f| f.first.to_s[filter.to_s]}
|
455
|
+
existing_filter.last.replace(opts)
|
456
|
+
else
|
457
|
+
filters << [filter, opts]
|
458
|
+
end
|
459
|
+
else
|
460
|
+
raise(ArgumentError,
|
461
|
+
'Filters need to be either a Symbol, String or a Proc'
|
462
|
+
)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
# Skip a filter that was previously added to the filter chain. Useful in
|
467
|
+
# inheritence hierarchies.
|
468
|
+
#
|
469
|
+
# ==== Parameters
|
470
|
+
# filters<Array[Filter]>:: The filter list that this should be removed from.
|
471
|
+
# filter<Filter>:: A filter that should be removed.
|
472
|
+
#
|
473
|
+
# ==== Raises
|
474
|
+
# ArgumentError:: filter not Symbol or String.
|
475
|
+
def self.skip_filter(filters, filter)
|
476
|
+
raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
|
477
|
+
[Symbol, String].include? filter.class
|
478
|
+
|
479
|
+
Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
|
480
|
+
filters.reject! {|f| f.first.to_s[filter.to_s] }
|
481
|
+
end
|
482
|
+
|
483
|
+
# Ensures that the passed in hash values are always arrays.
|
484
|
+
#
|
485
|
+
# ==== Parameters
|
486
|
+
# opts<Hash>:: Options for the filters (see below).
|
487
|
+
#
|
488
|
+
# ==== Options (opts)
|
489
|
+
# :only<Symbol, Array[Symbol]>:: A list of actions.
|
490
|
+
# :exclude<Symbol, Array[Symbol]>:: A list of actions.
|
491
|
+
#
|
492
|
+
# ==== Examples
|
493
|
+
# normalize_filters!(:only => :new) #=> {:only => [:new]}
|
494
|
+
def self.normalize_filters!(opts={})
|
495
|
+
opts[:only] = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
|
496
|
+
opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
|
497
|
+
return opts
|
498
|
+
end
|
499
|
+
|
500
|
+
# Calls the capture method for the selected template engine.
|
501
|
+
#
|
502
|
+
# ==== Parameters
|
503
|
+
# *args:: Arguments to pass to the block.
|
504
|
+
# &block:: The template block to call.
|
505
|
+
#
|
506
|
+
# ==== Returns
|
507
|
+
# String:: The output of the block.
|
508
|
+
def capture(*args, &block)
|
509
|
+
send("capture_#{@_engine}", *args, &block)
|
510
|
+
end
|
511
|
+
|
512
|
+
# Calls the concatenate method for the selected template engine.
|
513
|
+
#
|
514
|
+
# ==== Parameters
|
515
|
+
# str<String>:: The string to concatenate to the buffer.
|
516
|
+
# binding<Binding>:: The binding to use for the buffer.
|
517
|
+
def concat(str, binding)
|
518
|
+
send("concat_#{@_engine}", str, binding)
|
519
|
+
end
|
520
|
+
|
521
|
+
# Attempts to return the partial local variable corresponding to sym.
|
522
|
+
#
|
523
|
+
# ==== Paramteres
|
524
|
+
# sym<Symbol>:: Method name.
|
525
|
+
# *arg:: Arguments to pass to the method.
|
526
|
+
# &blk:: A block to pass to the method.
|
527
|
+
def method_missing(sym, *args, &blk)
|
528
|
+
return @_merb_partial_locals[sym] if @_merb_partial_locals && @_merb_partial_locals.key?(sym)
|
529
|
+
super
|
530
|
+
end
|
531
|
+
end
|