merb-core 0.9.2
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 +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
data/lib/merb-core.rb
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#---
|
|
2
|
+
# require 'merb' must happen after Merb::Config is instantiated
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'set'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'socket'
|
|
7
|
+
|
|
8
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) unless
|
|
9
|
+
$LOAD_PATH.include?(File.dirname(__FILE__)) ||
|
|
10
|
+
$LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
|
|
11
|
+
|
|
12
|
+
module Merb
|
|
13
|
+
module GlobalHelpers; end
|
|
14
|
+
class << self
|
|
15
|
+
|
|
16
|
+
# Startup Merb by setting up the Config and starting the server.
|
|
17
|
+
#
|
|
18
|
+
# ==== Parameters
|
|
19
|
+
# argv<String, Hash>::
|
|
20
|
+
# The config arguments to start Merb with. Defaults to +ARGV+.
|
|
21
|
+
def start(argv=ARGV)
|
|
22
|
+
if Hash === argv
|
|
23
|
+
Merb::Config.setup(argv)
|
|
24
|
+
else
|
|
25
|
+
Merb::Config.parse_args(argv)
|
|
26
|
+
end
|
|
27
|
+
Merb.environment = Merb::Config[:environment]
|
|
28
|
+
Merb.root = Merb::Config[:merb_root]
|
|
29
|
+
Merb::Server.start(Merb::Config[:port], Merb::Config[:cluster])
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Start the Merb environment, but only if it hasn't been loaded yet.
|
|
33
|
+
#
|
|
34
|
+
# ==== Parameters
|
|
35
|
+
# argv<String, Hash>::
|
|
36
|
+
# The config arguments to start Merb with. Defaults to +ARGV+.
|
|
37
|
+
def start_environment(argv=ARGV)
|
|
38
|
+
unless (@started ||= false)
|
|
39
|
+
start(argv)
|
|
40
|
+
@started = true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Restart the Merb environment explicitly.
|
|
45
|
+
#
|
|
46
|
+
# ==== Parameters
|
|
47
|
+
# argv<String, Hash>::
|
|
48
|
+
# The config arguments to restart Merb with. Defaults to +Merb::Config+.
|
|
49
|
+
def restart_environment(argv={})
|
|
50
|
+
@started = false
|
|
51
|
+
start_environment(Merb::Config.to_hash.merge(argv))
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
attr_accessor :environment, :load_paths, :adapter
|
|
55
|
+
|
|
56
|
+
alias :env :environment
|
|
57
|
+
|
|
58
|
+
Merb.load_paths = Hash.new { [Merb.root] } unless Merb.load_paths.is_a?(Hash)
|
|
59
|
+
|
|
60
|
+
# This is the core mechanism for setting up your application layout
|
|
61
|
+
# merb-core won't set a default application layout, but merb-more will
|
|
62
|
+
# use the app/:type layout that is in use in Merb 0.5.
|
|
63
|
+
#
|
|
64
|
+
# ==== Parameters
|
|
65
|
+
# type<Symbol>:: The type of path being registered (i.e. :view)
|
|
66
|
+
# path<String>:: The full path
|
|
67
|
+
# file_glob<String>::
|
|
68
|
+
# A glob that will be used to autoload files under the path. Defaults to
|
|
69
|
+
# "**/*.rb".
|
|
70
|
+
def push_path(type, path, file_glob = "**/*.rb")
|
|
71
|
+
enforce!(type => Symbol)
|
|
72
|
+
load_paths[type] = [path, file_glob]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def remove_paths(*args)
|
|
76
|
+
args.each {|arg| load_paths.delete(arg)}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# ==== Parameters
|
|
80
|
+
# type<Symbol>:: The type of path to retrieve directory for, e.g. :view.
|
|
81
|
+
#
|
|
82
|
+
# ==== Returns
|
|
83
|
+
# String:: The directory for the requested type.
|
|
84
|
+
def dir_for(type) Merb.load_paths[type].first end
|
|
85
|
+
|
|
86
|
+
# ==== Parameters
|
|
87
|
+
# type<Symbol>:: The type of path to retrieve glob for, e.g. :view.
|
|
88
|
+
#
|
|
89
|
+
# ===== Returns
|
|
90
|
+
# String:: The pattern with which to match files within the type directory.
|
|
91
|
+
def glob_for(type) Merb.load_paths[type][1] end
|
|
92
|
+
|
|
93
|
+
# ==== Returns
|
|
94
|
+
# String:: The Merb root path.
|
|
95
|
+
def root() @root || Merb::Config[:merb_root] || Dir.pwd end
|
|
96
|
+
|
|
97
|
+
# ==== Parameters
|
|
98
|
+
# value<String>:: Path to the root directory.
|
|
99
|
+
def root=(value) @root = value end
|
|
100
|
+
|
|
101
|
+
# ==== Parameters
|
|
102
|
+
# *path::
|
|
103
|
+
# The relative path (or list of path components) to a directory under the
|
|
104
|
+
# root of the application.
|
|
105
|
+
#
|
|
106
|
+
# ==== Returns
|
|
107
|
+
# String:: The full path including the root.
|
|
108
|
+
#
|
|
109
|
+
# ==== Examples
|
|
110
|
+
# Merb.root = "/home/merb/app"
|
|
111
|
+
# Merb.path("images") # => "/home/merb/app/images"
|
|
112
|
+
# Merb.path("views", "admin") # => "/home/merb/app/views/admin"
|
|
113
|
+
#---
|
|
114
|
+
# @public
|
|
115
|
+
def root_path(*path) File.join(root, *path) end
|
|
116
|
+
|
|
117
|
+
# Logger settings
|
|
118
|
+
attr_accessor :logger
|
|
119
|
+
|
|
120
|
+
# ==== Returns
|
|
121
|
+
# String::
|
|
122
|
+
# The path to the log file. If this Merb instance is running as a daemon
|
|
123
|
+
# this will return +STDOUT+.
|
|
124
|
+
def log_file
|
|
125
|
+
if Merb::Config[:log_file]
|
|
126
|
+
Merb::Config[:log_file]
|
|
127
|
+
elsif Merb.testing?
|
|
128
|
+
log_path / "merb_test.log"
|
|
129
|
+
elsif !(Merb::Config[:daemonize] || Merb::Config[:cluster])
|
|
130
|
+
STDOUT
|
|
131
|
+
else
|
|
132
|
+
log_path / "merb.#{Merb::Config[:port]}.log"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# ==== Returns
|
|
137
|
+
# String:: The directory that contains the log file.
|
|
138
|
+
def log_path
|
|
139
|
+
case Merb::Config[:log_file]
|
|
140
|
+
when String then File.dirname(Merb::Config[:log_file])
|
|
141
|
+
else Merb.root_path("log")
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# ==== Returns
|
|
146
|
+
# String:: The root directory of the Merb framework.
|
|
147
|
+
def framework_root() @framework_root ||= File.dirname(__FILE__) end
|
|
148
|
+
|
|
149
|
+
# Allows flat apps by setting no default framework directories and yielding
|
|
150
|
+
# a Merb::Router instance. This is optional since the router will
|
|
151
|
+
# automatically configure the app with default routes.
|
|
152
|
+
#
|
|
153
|
+
# ==== Block parameters
|
|
154
|
+
# r<Merb::Router::Behavior>::
|
|
155
|
+
# The root behavior upon which new routes can be added.
|
|
156
|
+
def flat!(framework = {})
|
|
157
|
+
Merb::Config[:framework] = framework
|
|
158
|
+
|
|
159
|
+
Merb::Router.prepare do |r|
|
|
160
|
+
yield(r) if block_given?
|
|
161
|
+
r.default_routes
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Set up default variables under Merb
|
|
166
|
+
attr_accessor :generator_scope, :klass_hashes
|
|
167
|
+
Merb.generator_scope = [:merb_default, :merb, :rspec]
|
|
168
|
+
Merb.klass_hashes = []
|
|
169
|
+
|
|
170
|
+
attr_reader :registered_session_types
|
|
171
|
+
|
|
172
|
+
# ==== Parameters
|
|
173
|
+
# name<~to_s>:: Name of the session type to register.
|
|
174
|
+
# file<String>:: The file that defines this session type.
|
|
175
|
+
# description<String>:: An optional description of the session type.
|
|
176
|
+
def register_session_type(name, file, description = nil)
|
|
177
|
+
@registered_session_types ||= Dictionary.new
|
|
178
|
+
@registered_session_types[name] = {
|
|
179
|
+
:file => file,
|
|
180
|
+
:description => (description || "Using #{name} sessions")
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
attr_accessor :frozen
|
|
185
|
+
|
|
186
|
+
# ==== Returns
|
|
187
|
+
# Boolean:: True if Merb is running via script/frozen-merb or other freezer.
|
|
188
|
+
def frozen?
|
|
189
|
+
@frozen
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Used by script/frozen-merb and other freezers to mark Merb as frozen.
|
|
193
|
+
def frozen!
|
|
194
|
+
@frozen = true
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Load configuration and assign logger.
|
|
198
|
+
#
|
|
199
|
+
# ==== Parameters
|
|
200
|
+
# options<Hash>:: Options to pass on to the Merb config.
|
|
201
|
+
def load_config(options = {})
|
|
202
|
+
Merb::Config.setup({ :log_file => STDOUT, :log_level => :warn, :log_auto_flush => true }.merge(options))
|
|
203
|
+
Merb::BootLoader::Logger.run
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Load all basic dependencies (selected BootLoaders only).
|
|
207
|
+
#
|
|
208
|
+
# ==== Parameters
|
|
209
|
+
# options<Hash>:: Options to pass on to the Merb config.
|
|
210
|
+
def load_dependencies(options = {})
|
|
211
|
+
load_config(options)
|
|
212
|
+
Merb::BootLoader::BuildFramework.run
|
|
213
|
+
Merb::BootLoader::Dependencies.run
|
|
214
|
+
Merb::BootLoader::BeforeAppRuns.run
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Reload the framework.
|
|
218
|
+
def reload
|
|
219
|
+
Merb::BootLoader::ReloadClasses.reload
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# ==== Returns
|
|
223
|
+
# Boolean:: True if Merb is running via spec_helper.rb or other TEST scenario.
|
|
224
|
+
def testing?
|
|
225
|
+
$TESTING || Merb::Config[:testing]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# If block was given configures using the block.
|
|
229
|
+
#
|
|
230
|
+
# ==== Parameters
|
|
231
|
+
# &block:: Configuration parameter block, see example below.
|
|
232
|
+
#
|
|
233
|
+
# ==== Returns
|
|
234
|
+
# Hash:: The current configuration.
|
|
235
|
+
#
|
|
236
|
+
# ==== Examples
|
|
237
|
+
# Merb.config do
|
|
238
|
+
# beer "good"
|
|
239
|
+
# hashish :foo => "bar"
|
|
240
|
+
# environment "development"
|
|
241
|
+
# log_level "debug"
|
|
242
|
+
# use_mutex false
|
|
243
|
+
# session_store "cookie"
|
|
244
|
+
# session_secret_key "0d05a226affa226623eb18700"
|
|
245
|
+
# exception_details true
|
|
246
|
+
# reload_classes true
|
|
247
|
+
# reload_time 0.5
|
|
248
|
+
# end
|
|
249
|
+
def config(&block)
|
|
250
|
+
Merb::Config.configure(&block) if block_given?
|
|
251
|
+
Config
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Disables the given core components, like a Gem for example.
|
|
255
|
+
#
|
|
256
|
+
# ==== Parameters
|
|
257
|
+
# *args:: One or more symbols of Merb internal components.
|
|
258
|
+
def disable(*components)
|
|
259
|
+
disabled_components.push *components
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# ==== Parameters
|
|
263
|
+
# Array:: All components that should be disabled.
|
|
264
|
+
def disabled_components=(components)
|
|
265
|
+
disabled_components.replace components
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# ==== Returns
|
|
269
|
+
# Array:: All components that have been disabled.
|
|
270
|
+
def disabled_components
|
|
271
|
+
Merb::Config[:disabled_components] ||= []
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# ==== Returns
|
|
275
|
+
# Boolean:: True if all components (or just one) are disabled.
|
|
276
|
+
def disabled?(*components)
|
|
277
|
+
components.all? { |c| disabled_components.include?(c) }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# ==== Returns
|
|
281
|
+
# Array:: All Rakefiles for plugins.
|
|
282
|
+
def rakefiles
|
|
283
|
+
@rakefiles ||= ['merb-core/test/tasks/spectasks']
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# ==== Parameters
|
|
287
|
+
# *rakefiles:: Rakefiles to add to the list of plugin Rakefiles.
|
|
288
|
+
def add_rakefiles(*rakefiles)
|
|
289
|
+
@rakefiles ||= ['merb-core/test/tasks/spectasks']
|
|
290
|
+
@rakefiles += rakefiles
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
require 'merb-core/autoload'
|
|
296
|
+
require 'merb-core/server'
|
|
297
|
+
require 'merb-core/gem_ext/erubis'
|
|
298
|
+
require 'merb-core/logger'
|
|
299
|
+
require 'merb-core/version'
|
|
300
|
+
require 'merb-core/controller/mime'
|
|
301
|
+
require 'merb-core/vendor/facets'
|
|
302
|
+
|
|
303
|
+
# Set the environment if it hasn't already been set.
|
|
304
|
+
Merb.environment ||= ENV['MERB_ENV'] || Merb::Config[:environment] || (Merb.testing? ? 'test' : 'development')
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
autoload :AbstractController, "merb-core/controller/abstract_controller"
|
|
3
|
+
autoload :BootLoader, "merb-core/bootloader"
|
|
4
|
+
autoload :Config, "merb-core/config"
|
|
5
|
+
autoload :Const, "merb-core/constants"
|
|
6
|
+
autoload :ControllerMixin, "merb-core/controller/mixins/controller"
|
|
7
|
+
autoload :ControllerExceptions, "merb-core/controller/exceptions"
|
|
8
|
+
autoload :Cookies, "merb-core/dispatch/cookies"
|
|
9
|
+
autoload :Dispatcher, "merb-core/dispatch/dispatcher"
|
|
10
|
+
autoload :ErubisCaptureMixin, "merb-core/controller/mixins/erubis_capture"
|
|
11
|
+
autoload :Plugins, "merb-core/plugins"
|
|
12
|
+
autoload :Rack, "merb-core/rack"
|
|
13
|
+
autoload :RenderMixin, "merb-core/controller/mixins/render"
|
|
14
|
+
autoload :Request, "merb-core/dispatch/request"
|
|
15
|
+
autoload :ResponderMixin, "merb-core/controller/mixins/responder"
|
|
16
|
+
autoload :Router, "merb-core/dispatch/router"
|
|
17
|
+
autoload :SessionMixin, "merb-core/dispatch/session"
|
|
18
|
+
autoload :Test, "merb-core/test"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Require this rather than autoloading it so we can be sure the default template
|
|
22
|
+
# gets registered
|
|
23
|
+
require 'merb-core/core_ext'
|
|
24
|
+
require "merb-core/controller/template"
|
|
25
|
+
require "merb-core/controller/merb_controller"
|
|
26
|
+
|
|
27
|
+
module Merb
|
|
28
|
+
module InlineTemplates; end
|
|
29
|
+
end
|
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
|
|
3
|
+
class BootLoader
|
|
4
|
+
|
|
5
|
+
# def self.subclasses
|
|
6
|
+
#---
|
|
7
|
+
# @semipublic
|
|
8
|
+
cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks
|
|
9
|
+
self.subclasses = []
|
|
10
|
+
self.after_load_callbacks = []
|
|
11
|
+
self.before_load_callbacks = []
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
|
|
15
|
+
# Adds the inheriting class to the list of subclasses in a position
|
|
16
|
+
# specified by the before and after methods.
|
|
17
|
+
#
|
|
18
|
+
# ==== Parameters
|
|
19
|
+
# klass<Class>:: The class inheriting from Merb::BootLoader.
|
|
20
|
+
def inherited(klass)
|
|
21
|
+
subclasses << klass.to_s
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# ==== Parameters
|
|
26
|
+
# klass<~to_s>::
|
|
27
|
+
# The boot loader class after which this boot loader should be run.
|
|
28
|
+
#
|
|
29
|
+
#---
|
|
30
|
+
# @public
|
|
31
|
+
def after(klass)
|
|
32
|
+
move_klass(klass, 1)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# ==== Parameters
|
|
36
|
+
# klass<~to_s>::
|
|
37
|
+
# The boot loader class before which this boot loader should be run.
|
|
38
|
+
#
|
|
39
|
+
#---
|
|
40
|
+
# @public
|
|
41
|
+
def before(klass)
|
|
42
|
+
move_klass(klass, 0)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Move a class that is inside the bootloader to some place in the Array,
|
|
46
|
+
# relative to another class.
|
|
47
|
+
#
|
|
48
|
+
# ==== Parameters
|
|
49
|
+
# klass<~to_s>::
|
|
50
|
+
# The klass to move the bootloader relative to
|
|
51
|
+
# where<Integer>::
|
|
52
|
+
# 0 means insert it before; 1 means insert it after
|
|
53
|
+
def move_klass(klass, where)
|
|
54
|
+
index = Merb::BootLoader.subclasses.index(klass.to_s)
|
|
55
|
+
if index
|
|
56
|
+
Merb::BootLoader.subclasses.delete(self.to_s)
|
|
57
|
+
Merb::BootLoader.subclasses.insert(index + where, self.to_s)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Runs all boot loader classes by calling their run methods.
|
|
62
|
+
def run
|
|
63
|
+
subklasses = subclasses.dup
|
|
64
|
+
until subclasses.empty?
|
|
65
|
+
bootloader = subclasses.shift
|
|
66
|
+
Merb.logger.debug!("Loading: #{bootloader}") if ENV['DEBUG']
|
|
67
|
+
Object.full_const_get(bootloader).run
|
|
68
|
+
end
|
|
69
|
+
self.subclasses = subklasses
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Set up the default framework
|
|
73
|
+
#
|
|
74
|
+
# ==== Returns
|
|
75
|
+
# nil
|
|
76
|
+
#
|
|
77
|
+
#---
|
|
78
|
+
# @public
|
|
79
|
+
def default_framework
|
|
80
|
+
%w[view model controller helper mailer part].each do |component|
|
|
81
|
+
Merb.push_path(component.to_sym, Merb.root_path("app/#{component}s"))
|
|
82
|
+
end
|
|
83
|
+
Merb.push_path(:application, Merb.root_path("app/controllers/application.rb"))
|
|
84
|
+
Merb.push_path(:config, Merb.root_path("config"), nil)
|
|
85
|
+
Merb.push_path(:router, Merb.dir_for(:config), (Merb::Config[:router_file] || "router.rb"))
|
|
86
|
+
Merb.push_path(:lib, Merb.root_path("lib"), nil)
|
|
87
|
+
Merb.push_path(:log, Merb.log_path, nil)
|
|
88
|
+
Merb.push_path(:public, Merb.root_path("public"), nil)
|
|
89
|
+
Merb.push_path(:stylesheet, Merb.dir_for(:public) / "stylesheets", nil)
|
|
90
|
+
Merb.push_path(:javascript, Merb.dir_for(:public) / "javascripts", nil)
|
|
91
|
+
Merb.push_path(:image, Merb.dir_for(:public) / "images", nil)
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# ==== Parameters
|
|
96
|
+
# &block::
|
|
97
|
+
# A block to be added to the callbacks that will be executed after the
|
|
98
|
+
# app loads.
|
|
99
|
+
#
|
|
100
|
+
#---
|
|
101
|
+
# @public
|
|
102
|
+
def after_app_loads(&block)
|
|
103
|
+
after_load_callbacks << block
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# ==== Parameters
|
|
107
|
+
# &block::
|
|
108
|
+
# A block to be added to the callbacks that will be executed before the
|
|
109
|
+
# app loads.
|
|
110
|
+
#
|
|
111
|
+
#---
|
|
112
|
+
# @public
|
|
113
|
+
def before_app_loads(&block)
|
|
114
|
+
before_load_callbacks << block
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Set up the logger.
|
|
123
|
+
#
|
|
124
|
+
# Place the logger inside of the Merb log directory (set up in
|
|
125
|
+
# Merb::BootLoader::BuildFramework)
|
|
126
|
+
class Merb::BootLoader::Logger < Merb::BootLoader
|
|
127
|
+
|
|
128
|
+
# Sets Merb.logger to a new logger created based on the config settings.
|
|
129
|
+
def self.run
|
|
130
|
+
Merb.logger = Merb::Logger.new(Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush])
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class Merb::BootLoader::DropPidFile < Merb::BootLoader
|
|
135
|
+
class << self
|
|
136
|
+
|
|
137
|
+
# Stores a PID file if Merb is running daemonized or clustered.
|
|
138
|
+
def run
|
|
139
|
+
Merb::Server.store_pid(Merb::Config[:port]) if Merb::Config[:daemonize] || Merb::Config[:cluster]
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Build the framework paths.
|
|
145
|
+
#
|
|
146
|
+
# By default, the following paths will be used:
|
|
147
|
+
# application:: Merb.root/app/controller/application.rb
|
|
148
|
+
# config:: Merb.root/config
|
|
149
|
+
# lib:: Merb.root/lib
|
|
150
|
+
# log:: Merb.root/log
|
|
151
|
+
# view:: Merb.root/app/views
|
|
152
|
+
# model:: Merb.root/app/models
|
|
153
|
+
# controller:: Merb.root/app/controllers
|
|
154
|
+
# helper:: Merb.root/app/helpers
|
|
155
|
+
# mailer:: Merb.root/app/mailers
|
|
156
|
+
# part:: Merb.root/app/parts
|
|
157
|
+
#
|
|
158
|
+
# To override the default, set Merb::Config[:framework] in your initialization
|
|
159
|
+
# file. Merb::Config[:framework] takes a Hash whose key is the name of the
|
|
160
|
+
# path, and whose values can be passed into Merb.push_path (see Merb.push_path
|
|
161
|
+
# for full details).
|
|
162
|
+
#
|
|
163
|
+
# ==== Note
|
|
164
|
+
# All paths will default to Merb.root, so you can get a flat-file structure by
|
|
165
|
+
# doing Merb::Config[:framework] = {}.
|
|
166
|
+
#
|
|
167
|
+
# ==== Example
|
|
168
|
+
# Merb::Config[:framework] = {
|
|
169
|
+
# :view => Merb.root / "views"
|
|
170
|
+
# :model => Merb.root / "models"
|
|
171
|
+
# :lib => Merb.root / "lib"
|
|
172
|
+
# }
|
|
173
|
+
#
|
|
174
|
+
# That will set up a flat directory structure with the config files and
|
|
175
|
+
# controller files under Merb.root, but with models, views, and lib with their
|
|
176
|
+
# own folders off of Merb.root.
|
|
177
|
+
class Merb::BootLoader::BuildFramework < Merb::BootLoader
|
|
178
|
+
class << self
|
|
179
|
+
|
|
180
|
+
# Builds the framework directory structure.
|
|
181
|
+
def run
|
|
182
|
+
build_framework
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# This method should be overridden in init.rb before Merb.start to set up
|
|
186
|
+
# a different framework structure.
|
|
187
|
+
def build_framework
|
|
188
|
+
if File.exists?(Merb.root / "config" / "framework.rb")
|
|
189
|
+
require Merb.root / "config" / "framework"
|
|
190
|
+
elsif File.exists?(Merb.root / "framework.rb")
|
|
191
|
+
require Merb.root / "framework"
|
|
192
|
+
else
|
|
193
|
+
Merb::BootLoader.default_framework
|
|
194
|
+
end
|
|
195
|
+
(Merb::Config[:framework] || {}).each do |name, path|
|
|
196
|
+
path = [path].flatten
|
|
197
|
+
Merb.push_path(name, Merb.root_path(path.first), path[1])
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
204
|
+
|
|
205
|
+
cattr_accessor :dependencies
|
|
206
|
+
self.dependencies = []
|
|
207
|
+
|
|
208
|
+
# Load the init_file specified in Merb::Config or if not specified, the
|
|
209
|
+
# init.rb file from the Merb configuration directory, and any environment
|
|
210
|
+
# files, which register the list of necessary dependencies and any
|
|
211
|
+
# after_app_loads hooks.
|
|
212
|
+
#
|
|
213
|
+
# Dependencies can hook into the bootloader process itself by using
|
|
214
|
+
# before or after insertion methods. Since these are loaded from this
|
|
215
|
+
# bootloader (Dependencies), they can only adapt the bootloaders that
|
|
216
|
+
# haven't been loaded up until this point.
|
|
217
|
+
|
|
218
|
+
def self.run
|
|
219
|
+
load_initfile
|
|
220
|
+
load_env_config
|
|
221
|
+
enable_json_gem unless Merb::disabled?(:json)
|
|
222
|
+
load_dependencies
|
|
223
|
+
update_logger
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def self.load_dependencies
|
|
227
|
+
dependencies.each { |name, ver| Kernel.load_dependency(name, *ver) }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def self.enable_json_gem
|
|
231
|
+
require "json/ext"
|
|
232
|
+
rescue LoadError
|
|
233
|
+
require "json/pure"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def self.update_logger
|
|
237
|
+
updated_logger_options = [ Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush] ]
|
|
238
|
+
Merb::BootLoader::Logger.run if updated_logger_options != Merb.logger.init_args
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
private
|
|
242
|
+
|
|
243
|
+
# Determines the path for the environment configuration file
|
|
244
|
+
def self.env_config
|
|
245
|
+
Merb.dir_for(:config) / "environments" / (Merb.environment + ".rb")
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# Checks to see whether or not an environment configuration exists
|
|
249
|
+
def self.env_config?
|
|
250
|
+
Merb.environment && File.exist?(env_config)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Loads the environment configuration file, if any
|
|
254
|
+
def self.load_env_config
|
|
255
|
+
load(env_config) if env_config?
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Determines the init file to use, if any
|
|
259
|
+
def self.initfile
|
|
260
|
+
if Merb::Config[:init_file]
|
|
261
|
+
Merb::Config[:init_file].chomp(".rb") + ".rb"
|
|
262
|
+
else
|
|
263
|
+
Merb.dir_for(:config) / "init.rb"
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Loads the init file, should one exist
|
|
268
|
+
def self.load_initfile
|
|
269
|
+
load(initfile) if File.exists?(initfile)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
class Merb::BootLoader::BeforeAppRuns < Merb::BootLoader
|
|
275
|
+
|
|
276
|
+
# Call any before_app_loads hooks that were registered via before_app_loads
|
|
277
|
+
# in any plugins.
|
|
278
|
+
def self.run
|
|
279
|
+
Merb::BootLoader.before_load_callbacks.each { |x| x.call }
|
|
280
|
+
end
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Load all classes inside the load paths.
|
|
284
|
+
#
|
|
285
|
+
# This is used in conjunction with Merb::BootLoader::ReloadClasses to track
|
|
286
|
+
# files that need to be reloaded, and which constants need to be removed in
|
|
287
|
+
# order to reload a file.
|
|
288
|
+
#
|
|
289
|
+
# This also adds the model, controller, and lib directories to the load path,
|
|
290
|
+
# so they can be required in order to avoid load-order issues.
|
|
291
|
+
class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
292
|
+
LOADED_CLASSES = {}
|
|
293
|
+
MTIMES = {}
|
|
294
|
+
|
|
295
|
+
class << self
|
|
296
|
+
|
|
297
|
+
# Load all classes inside the load paths.
|
|
298
|
+
def run
|
|
299
|
+
orphaned_classes = []
|
|
300
|
+
# Add models, controllers, and lib to the load path
|
|
301
|
+
$LOAD_PATH.unshift Merb.dir_for(:model)
|
|
302
|
+
$LOAD_PATH.unshift Merb.dir_for(:controller)
|
|
303
|
+
$LOAD_PATH.unshift Merb.dir_for(:lib)
|
|
304
|
+
|
|
305
|
+
load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application))
|
|
306
|
+
|
|
307
|
+
# Require all the files in the registered load paths
|
|
308
|
+
Merb.load_paths.each do |name, path|
|
|
309
|
+
next unless path.last && name != :application
|
|
310
|
+
Dir[path.first / path.last].each do |file|
|
|
311
|
+
|
|
312
|
+
begin
|
|
313
|
+
load_file file
|
|
314
|
+
rescue NameError => ne
|
|
315
|
+
orphaned_classes.unshift(file)
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
Merb::Controller.send :include, Merb::GlobalHelpers
|
|
320
|
+
|
|
321
|
+
load_classes_with_requirements(orphaned_classes)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# ==== Parameters
|
|
325
|
+
# file<String>:: The file to load.
|
|
326
|
+
def load_file(file)
|
|
327
|
+
klasses = ObjectSpace.classes.dup
|
|
328
|
+
load file
|
|
329
|
+
LOADED_CLASSES[file] = ObjectSpace.classes - klasses
|
|
330
|
+
MTIMES[file] = File.mtime(file)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# "Better loading" of classes. If a class fails to load due to a NameError
|
|
334
|
+
# it will be added to the failed_classs stack.
|
|
335
|
+
#
|
|
336
|
+
# ==== Parameters
|
|
337
|
+
# klasses<Array[Class]>:: Classes to load.
|
|
338
|
+
def load_classes_with_requirements(klasses)
|
|
339
|
+
klasses.uniq!
|
|
340
|
+
|
|
341
|
+
while klasses.size > 0
|
|
342
|
+
# note size to make sure things are loading
|
|
343
|
+
size_at_start = klasses.size
|
|
344
|
+
|
|
345
|
+
#list of failed classes
|
|
346
|
+
failed_classes = []
|
|
347
|
+
|
|
348
|
+
klasses.each do |klass|
|
|
349
|
+
klasses.delete(klass)
|
|
350
|
+
begin
|
|
351
|
+
load_file klass
|
|
352
|
+
rescue NameError => ne
|
|
353
|
+
failed_classes.push(klass)
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# keep list of classes unique
|
|
358
|
+
failed_classes.each { |k| klasses.push(k) unless klasses.include?(k) }
|
|
359
|
+
|
|
360
|
+
#stop processing if nothing loads or if everything has loaded
|
|
361
|
+
if klasses.size == size_at_start && klasses.size != 0
|
|
362
|
+
raise LoadError, "Could not load #{failed_classes.inspect}."
|
|
363
|
+
end
|
|
364
|
+
break if(klasses.size == size_at_start || klasses.size == 0)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
# ==== Parameters
|
|
369
|
+
# file<String>:: The file to reload.
|
|
370
|
+
def reload(file)
|
|
371
|
+
Merb.klass_hashes.each {|x| x.protect_keys!}
|
|
372
|
+
if klasses = LOADED_CLASSES.delete(file)
|
|
373
|
+
klasses.each { |klass| remove_constant(klass) unless klass.to_s =~ /Router/ }
|
|
374
|
+
end
|
|
375
|
+
load_file file
|
|
376
|
+
Merb.klass_hashes.each {|x| x.unprotect_keys!}
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# ==== Parameters
|
|
380
|
+
# const<Class>:: The class to remove.
|
|
381
|
+
def remove_constant(const)
|
|
382
|
+
# This is to support superclasses (like AbstractController) that track
|
|
383
|
+
# their subclasses in a class variable. Classes that wish to use this
|
|
384
|
+
# functionality are required to alias it to _subclasses_list. Plugins
|
|
385
|
+
# for ORMs and other libraries should keep this in mind.
|
|
386
|
+
superklass = const
|
|
387
|
+
until (superklass = superklass.superclass).nil?
|
|
388
|
+
if superklass.respond_to?(:_subclasses_list)
|
|
389
|
+
superklass.send(:_subclasses_list).delete(klass)
|
|
390
|
+
superklass.send(:_subclasses_list).delete(klass.to_s)
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
parts = const.to_s.split("::")
|
|
395
|
+
base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
|
|
396
|
+
object = parts[-1].to_s
|
|
397
|
+
begin
|
|
398
|
+
base.send(:remove_const, object)
|
|
399
|
+
Merb.logger.debug("Removed constant #{object} from #{base}")
|
|
400
|
+
rescue NameError
|
|
401
|
+
Merb.logger.debug("Failed to remove constant #{object} from #{base}")
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
class Merb::BootLoader::Templates < Merb::BootLoader
|
|
409
|
+
class << self
|
|
410
|
+
|
|
411
|
+
# Loads the templates into the Merb::InlineTemplates module.
|
|
412
|
+
def run
|
|
413
|
+
template_paths.each do |path|
|
|
414
|
+
Merb::Template.inline_template(path)
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
# ==== Returns
|
|
419
|
+
# Array[String]:: Template files found.
|
|
420
|
+
def template_paths
|
|
421
|
+
extension_glob = "{#{Merb::Template::EXTENSIONS.keys.join(',')}}"
|
|
422
|
+
|
|
423
|
+
# This gets all templates set in the controllers template roots
|
|
424
|
+
# We separate the two maps because most of controllers will have
|
|
425
|
+
# the same _template_root, so it's silly to be globbing the same
|
|
426
|
+
# path over and over.
|
|
427
|
+
template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
|
|
428
|
+
Object.full_const_get(klass)._template_root
|
|
429
|
+
end.uniq.compact.map {|path| Dir["#{path}/**/*.#{extension_glob}"] }
|
|
430
|
+
|
|
431
|
+
# This gets the templates that might be created outside controllers
|
|
432
|
+
# template roots. eg app/views/shared/*
|
|
433
|
+
template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
|
|
434
|
+
|
|
435
|
+
template_paths.flatten.compact.uniq
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
# Register the default MIME types:
|
|
441
|
+
#
|
|
442
|
+
# By default, the mime-types include:
|
|
443
|
+
# :all:: no transform, */*
|
|
444
|
+
# :yaml:: to_yaml, application/x-yaml or text/yaml
|
|
445
|
+
# :text:: to_text, text/plain
|
|
446
|
+
# :html:: to_html, text/html or application/xhtml+xml or application/html
|
|
447
|
+
# :xml:: to_xml, application/xml or text/xml or application/x-xml, adds "Encoding: UTF-8" response header
|
|
448
|
+
# :js:: to_json, text/javascript ot application/javascript or application/x-javascript
|
|
449
|
+
# :json:: to_json, application/json or text/x-json
|
|
450
|
+
class Merb::BootLoader::MimeTypes < Merb::BootLoader
|
|
451
|
+
|
|
452
|
+
# Registers the default MIME types.
|
|
453
|
+
def self.run
|
|
454
|
+
Merb.add_mime_type(:all, nil, %w[*/*])
|
|
455
|
+
Merb.add_mime_type(:yaml, :to_yaml, %w[application/x-yaml text/yaml])
|
|
456
|
+
Merb.add_mime_type(:text, :to_text, %w[text/plain])
|
|
457
|
+
Merb.add_mime_type(:html, :to_html, %w[text/html application/xhtml+xml application/html])
|
|
458
|
+
Merb.add_mime_type(:xml, :to_xml, %w[application/xml text/xml application/x-xml], :Encoding => "UTF-8")
|
|
459
|
+
Merb.add_mime_type(:js, :to_json, %w[text/javascript application/javascript application/x-javascript])
|
|
460
|
+
Merb.add_mime_type(:json, :to_json, %w[application/json text/x-json])
|
|
461
|
+
end
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
class Merb::BootLoader::AfterAppLoads < Merb::BootLoader
|
|
465
|
+
|
|
466
|
+
# Call any after_app_loads hooks that were registered via after_app_loads in
|
|
467
|
+
# init.rb.
|
|
468
|
+
def self.run
|
|
469
|
+
Merb::BootLoader.after_load_callbacks.each {|x| x.call }
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
class Merb::BootLoader::MixinSessionContainer < Merb::BootLoader
|
|
474
|
+
|
|
475
|
+
# Mixin the correct session container.
|
|
476
|
+
def self.run
|
|
477
|
+
Merb.register_session_type('memory',
|
|
478
|
+
Merb.framework_root / "merb-core" / "dispatch" / "session" / "memory",
|
|
479
|
+
"Using in-memory sessions; sessions will be lost whenever the server stops.")
|
|
480
|
+
|
|
481
|
+
Merb.register_session_type('memcache',
|
|
482
|
+
Merb.framework_root / "merb-core" / "dispatch" / "session" / "memcached",
|
|
483
|
+
"Using 'memcached' sessions")
|
|
484
|
+
|
|
485
|
+
Merb.register_session_type('cookie', # Last session type becomes the default
|
|
486
|
+
Merb.framework_root / "merb-core" / "dispatch" / "session" / "cookie",
|
|
487
|
+
"Using 'share-nothing' cookie sessions (4kb limit per client)")
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
Merb::Controller.class_eval do
|
|
492
|
+
session_store = Merb::Config[:session_store].to_s
|
|
493
|
+
if ["", "false", "none"].include?(session_store)
|
|
494
|
+
Merb.logger.warn "Not Using Sessions"
|
|
495
|
+
elsif reg = Merb.registered_session_types[session_store]
|
|
496
|
+
if session_store == "cookie"
|
|
497
|
+
Merb::BootLoader::MixinSessionContainer.check_for_secret_key
|
|
498
|
+
Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
|
|
499
|
+
end
|
|
500
|
+
require reg[:file]
|
|
501
|
+
include ::Merb::SessionMixin
|
|
502
|
+
Merb.logger.warn reg[:description]
|
|
503
|
+
else
|
|
504
|
+
Merb.logger.warn "Session store not found, '#{Merb::Config[:session_store]}'."
|
|
505
|
+
Merb.logger.warn "Defaulting to CookieStore Sessions"
|
|
506
|
+
Merb::BootLoader::MixinSessionContainer.check_for_secret_key
|
|
507
|
+
Merb::BootLoader::MixinSessionContainer.check_for_session_id_key
|
|
508
|
+
require Merb.registered_session_types['cookie'][:file]
|
|
509
|
+
include ::Merb::SessionMixin
|
|
510
|
+
Merb.logger.warn "(plugin not installed?)"
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
Merb.logger.flush
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
# Sets the controller session ID key if it has been set in config.
|
|
518
|
+
def self.check_for_session_id_key
|
|
519
|
+
if Merb::Config[:session_id_key]
|
|
520
|
+
Merb::Controller._session_id_key = Merb::Config[:session_id_key]
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
# Attempts to set the session secret key. This method will exit if the key
|
|
525
|
+
# does not exist or is shorter than 16 charaters.
|
|
526
|
+
def self.check_for_secret_key
|
|
527
|
+
unless Merb::Config[:session_secret_key] && (Merb::Config[:session_secret_key].length >= 16)
|
|
528
|
+
Merb.logger.warn("You must specify a session_secret_key in your merb.yml, and it must be at least 16 characters\nbailing out...")
|
|
529
|
+
exit!
|
|
530
|
+
end
|
|
531
|
+
Merb::Controller._session_secret_key = Merb::Config[:session_secret_key]
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
class Merb::BootLoader::ChooseAdapter < Merb::BootLoader
|
|
536
|
+
|
|
537
|
+
# Choose the Rack adapter/server to use and set Merb.adapter.
|
|
538
|
+
def self.run
|
|
539
|
+
Merb.adapter = Merb::Rack::Adapter.get(Merb::Config[:adapter])
|
|
540
|
+
end
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
class Merb::BootLoader::RackUpApplication < Merb::BootLoader
|
|
544
|
+
|
|
545
|
+
# Setup the Merb Rack App or read a rack.rb config file located at the
|
|
546
|
+
# Merb.root or Merb.root / config / rack.rb with the same syntax as the
|
|
547
|
+
# rackup tool that comes with rack. Automatically evals the rack.rb file in
|
|
548
|
+
# the context of a Rack::Builder.new { } block. Allows for mounting
|
|
549
|
+
# additional apps or middleware.
|
|
550
|
+
def self.run
|
|
551
|
+
if File.exists?(Merb.dir_for(:config) / "rack.rb")
|
|
552
|
+
Merb::Config[:app] = eval("::Rack::Builder.new {( #{IO.read(Merb.dir_for(:config) / 'rack.rb')}\n )}.to_app", TOPLEVEL_BINDING, __FILE__, __LINE__)
|
|
553
|
+
else
|
|
554
|
+
Merb::Config[:app] = ::Merb::Rack::Application.new
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
class Merb::BootLoader::ReloadClasses < Merb::BootLoader
|
|
560
|
+
|
|
561
|
+
# Setup the class reloader if it's been specified in config.
|
|
562
|
+
def self.run
|
|
563
|
+
return unless Merb::Config[:reload_classes]
|
|
564
|
+
|
|
565
|
+
Thread.abort_on_exception = true
|
|
566
|
+
Thread.new do
|
|
567
|
+
loop do
|
|
568
|
+
sleep( Merb::Config[:reload_time] || 0.5 )
|
|
569
|
+
reload
|
|
570
|
+
end
|
|
571
|
+
Thread.exit
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
# Reloads all files.
|
|
576
|
+
def self.reload
|
|
577
|
+
paths = []
|
|
578
|
+
Merb.load_paths.each do |path_name, file_info|
|
|
579
|
+
path, glob = file_info
|
|
580
|
+
next unless glob
|
|
581
|
+
paths << Dir[path / glob]
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
paths << Merb.dir_for(:application) if Merb.dir_for(:application) && File.file?(Merb.dir_for(:application))
|
|
585
|
+
|
|
586
|
+
paths.flatten.each do |file|
|
|
587
|
+
next if Merb::BootLoader::LoadClasses::MTIMES[file] && Merb::BootLoader::LoadClasses::MTIMES[file] == File.mtime(file)
|
|
588
|
+
Merb::BootLoader::LoadClasses.reload(file)
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
class Merb::BootLoader::ReloadTemplates < Merb::BootLoader
|
|
594
|
+
|
|
595
|
+
# Reloads all templates if the reload_templates key has been set in config.
|
|
596
|
+
def self.run
|
|
597
|
+
unless Merb::Config.key?(:reload_templates)
|
|
598
|
+
Merb::Config[:reload_templates] = (Merb.environment == "development")
|
|
599
|
+
end
|
|
600
|
+
end
|
|
601
|
+
end
|