merb 0.4.2 → 0.5.0
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/README +21 -14
- data/Rakefile +157 -108
- data/SVN_REVISION +1 -0
- data/app_generators/merb/templates/Rakefile +20 -4
- data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +1 -1
- data/app_generators/merb/templates/config/boot.rb +1 -1
- data/app_generators/merb/templates/config/dependencies.rb +3 -3
- data/app_generators/merb/templates/config/merb.yml +5 -0
- data/app_generators/merb/templates/config/merb_init.rb +3 -3
- data/app_generators/merb/templates/script/destroy +3 -0
- data/app_generators/merb/templates/script/generate +1 -1
- data/app_generators/merb/templates/spec/spec_helper.rb +2 -2
- data/app_generators/merb/templates/test/test_helper.rb +1 -1
- data/app_generators/merb_plugin/merb_plugin_generator.rb +4 -0
- data/bin/merb +1 -3
- data/lib/merb.rb +144 -76
- data/lib/merb/abstract_controller.rb +6 -5
- data/lib/merb/assets.rb +119 -0
- data/lib/merb/boot_loader.rb +217 -0
- data/lib/merb/caching.rb +1 -1
- data/lib/merb/caching/action_cache.rb +1 -1
- data/lib/merb/caching/fragment_cache.rb +1 -1
- data/lib/merb/caching/store/file_cache.rb +1 -1
- data/lib/merb/config.rb +290 -0
- data/lib/merb/controller.rb +5 -5
- data/lib/merb/core_ext/get_args.rb +1 -0
- data/lib/merb/core_ext/hash.rb +182 -169
- data/lib/merb/core_ext/kernel.rb +57 -26
- data/lib/merb/dispatcher.rb +6 -6
- data/lib/merb/drb_server.rb +1 -1
- data/lib/merb/generators/merb_generator_helpers.rb +7 -6
- data/lib/merb/logger.rb +1 -1
- data/lib/merb/mail_controller.rb +3 -4
- data/lib/merb/mailer.rb +2 -2
- data/lib/merb/mixins/basic_authentication.rb +2 -2
- data/lib/merb/mixins/controller.rb +1 -1
- data/lib/merb/mixins/general_controller.rb +13 -20
- data/lib/merb/mixins/inline_partial.rb +32 -0
- data/lib/merb/mixins/render.rb +3 -3
- data/lib/merb/mixins/responder.rb +1 -1
- data/lib/merb/mixins/view_context.rb +159 -33
- data/lib/merb/mongrel_handler.rb +9 -9
- data/lib/merb/plugins.rb +1 -1
- data/lib/merb/request.rb +25 -1
- data/lib/merb/router.rb +264 -226
- data/lib/merb/server.rb +66 -560
- data/lib/merb/session/cookie_store.rb +14 -13
- data/lib/merb/session/mem_cache_session.rb +20 -10
- data/lib/merb/session/memory_session.rb +21 -11
- data/lib/merb/template.rb +2 -2
- data/lib/merb/template/erubis.rb +3 -33
- data/lib/merb/template/haml.rb +8 -3
- data/lib/merb/test/fake_request.rb +8 -3
- data/lib/merb/test/helper.rb +66 -22
- data/lib/merb/test/rspec.rb +9 -155
- data/lib/merb/test/rspec_matchers/controller_matchers.rb +117 -0
- data/lib/merb/test/rspec_matchers/markup_matchers.rb +98 -0
- data/lib/merb/upload_handler.rb +2 -1
- data/lib/merb/version.rb +38 -3
- data/lib/merb/view_context.rb +1 -2
- data/lib/tasks/merb.rake +11 -11
- data/merb_generators/part_controller/USAGE +5 -0
- data/merb_generators/part_controller/part_controller_generator.rb +27 -0
- data/merb_generators/part_controller/templates/controller.rb +8 -0
- data/merb_generators/part_controller/templates/helper.rb +5 -0
- data/merb_generators/part_controller/templates/index.html.erb +3 -0
- data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +1 -1
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/fixtures/controllers/dispatch_spec_controllers.rb +9 -1
- data/spec/fixtures/controllers/render_spec_controllers.rb +5 -5
- data/spec/fixtures/models/router_spec_models.rb +10 -0
- data/spec/merb/abstract_controller_spec.rb +2 -2
- data/spec/merb/assets_spec.rb +207 -0
- data/spec/merb/caching_spec.rb +2 -2
- data/spec/merb/controller_spec.rb +7 -2
- data/spec/merb/cookie_store_spec.rb +1 -1
- data/spec/merb/core_ext/class_spec.rb +97 -0
- data/spec/merb/core_ext/enumerable_spec.rb +27 -0
- data/spec/merb/core_ext/hash_spec.rb +251 -0
- data/spec/merb/core_ext/inflector_spec.rb +34 -0
- data/spec/merb/core_ext/kernel_spec.rb +25 -0
- data/spec/merb/core_ext/numeric_spec.rb +26 -0
- data/spec/merb/core_ext/object_spec.rb +47 -0
- data/spec/merb/core_ext/string_spec.rb +22 -0
- data/spec/merb/core_ext/symbol_spec.rb +7 -0
- data/spec/merb/dependency_spec.rb +22 -0
- data/spec/merb/dispatch_spec.rb +23 -12
- data/spec/merb/fake_request_spec.rb +8 -0
- data/spec/merb/generator_spec.rb +140 -21
- data/spec/merb/handler_spec.rb +5 -5
- data/spec/merb/mail_controller_spec.rb +3 -3
- data/spec/merb/render_spec.rb +1 -1
- data/spec/merb/responder_spec.rb +3 -3
- data/spec/merb/router_spec.rb +260 -191
- data/spec/merb/server_spec.rb +5 -5
- data/spec/merb/upload_handler_spec.rb +7 -0
- data/spec/merb/version_spec.rb +33 -0
- data/spec/merb/view_context_spec.rb +217 -59
- data/spec/spec_generator_helper.rb +15 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/spec_helpers/url_shared_behaviour.rb +5 -7
- metadata +32 -7
- data/lib/merb/caching/store/memcache.rb +0 -20
- data/lib/merb/mixins/form_control.rb +0 -332
- data/lib/patch +0 -69
- data/spec/merb/core_ext_spec.rb +0 -464
- data/spec/merb/form_control_mixin_spec.rb +0 -431
data/lib/merb/server.rb
CHANGED
|
@@ -1,580 +1,88 @@
|
|
|
1
1
|
require 'rubygems'
|
|
2
|
+
|
|
3
|
+
# Make the app's "gems" directory a place where gems are loaded from
|
|
4
|
+
# This needs to go here for using in a shared envirionment where Erubis may not
|
|
5
|
+
# be available
|
|
6
|
+
if File.exists?(File.join(Dir.pwd, "gems")) && File.directory?(File.join(Dir.pwd,"gems"))
|
|
7
|
+
Gem.clear_paths
|
|
8
|
+
Gem.path.unshift(File.join(Dir.pwd,"gems"))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
2
12
|
require 'optparse'
|
|
3
13
|
require 'ostruct'
|
|
4
14
|
require 'fileutils'
|
|
5
15
|
require 'yaml'
|
|
6
16
|
|
|
7
|
-
|
|
8
|
-
|
|
17
|
+
# this is so we can test for HAML features for HAML partial inlining
|
|
18
|
+
unless Gem.cache.search("haml").empty?
|
|
19
|
+
gem "haml"
|
|
20
|
+
require "haml"
|
|
21
|
+
end
|
|
9
22
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
module GlobalHelper
|
|
13
|
-
end
|
|
23
|
+
require File.join(File.dirname(__FILE__), 'config')
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
class << self
|
|
17
|
-
def defaults
|
|
18
|
-
@defaults ||= {
|
|
19
|
-
:host => "0.0.0.0",
|
|
20
|
-
:port => "4000",
|
|
21
|
-
:reloader => true,
|
|
22
|
-
:cache_templates => false,
|
|
23
|
-
:merb_root => Dir.pwd,
|
|
24
|
-
:use_mutex => true,
|
|
25
|
-
:session_id_cookie_only => true,
|
|
26
|
-
:query_string_whitelist => [],
|
|
27
|
-
:mongrel_x_sendfile => true
|
|
28
|
-
}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def setup(global_merb_yml = nil)
|
|
32
|
-
if FileTest.exist? "#{defaults[:merb_root]}/framework"
|
|
33
|
-
$LOAD_PATH.unshift( "#{defaults[:merb_root]}/framework" )
|
|
34
|
-
end
|
|
35
|
-
global_merb_yml ||= "#{defaults[:merb_root]}/config/merb.yml"
|
|
36
|
-
apply_configuration_from_file defaults, global_merb_yml
|
|
37
|
-
end
|
|
25
|
+
module Merb
|
|
38
26
|
|
|
39
|
-
def apply_configuration_from_file(configuration, file)
|
|
40
|
-
if File.exists?(file)
|
|
41
|
-
configuration.merge(Erubis.load_yaml_file(file))
|
|
42
|
-
else
|
|
43
|
-
configuration
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
27
|
class Server
|
|
50
28
|
|
|
51
29
|
class << self
|
|
52
30
|
|
|
53
|
-
def merb_config(argv = ARGV)
|
|
54
|
-
# Our primary configuration hash for the length of this method
|
|
55
|
-
options = {}
|
|
56
|
-
|
|
57
|
-
# Environment variables always win
|
|
58
|
-
options[:environment] = ENV['MERB_ENV']
|
|
59
|
-
|
|
60
|
-
# Build a parser for the command line arguements
|
|
61
|
-
opts = OptionParser.new do |opts|
|
|
62
|
-
opts.version = Merb::VERSION
|
|
63
|
-
opts.release = Merb::RELEASE
|
|
64
|
-
|
|
65
|
-
opts.banner = "Usage: merb [fdcepghmisluMG] [argument]"
|
|
66
|
-
opts.define_head "Merb Mongrel+ Erb. Lightweight replacement for ActionPack."
|
|
67
|
-
opts.separator '*'*80
|
|
68
|
-
opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
|
|
69
|
-
opts.separator '*'*80
|
|
70
|
-
|
|
71
|
-
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 |config|
|
|
72
|
-
options[:user] = config
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
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 |config|
|
|
76
|
-
options[:group] = config
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
opts.on("-f", "--config-file FILENAME", "This flag is for adding extra config files for things like the upload progress module.") do |config|
|
|
80
|
-
options[:config] = config
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
opts.on("-d", "--daemonize", "This will run a single merb in the background.") do |config|
|
|
84
|
-
options[:daemonize] = true
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run.") do |nodes|
|
|
88
|
-
options[:cluster] = nodes
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
|
|
92
|
-
options[:port] = port
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
opts.on("-h", "--host HOSTNAME", "Host to bind to (default is all IP's).") do |host|
|
|
96
|
-
if host
|
|
97
|
-
options[:host] = host
|
|
98
|
-
else
|
|
99
|
-
# If no host was given, assume they meant they wanted help.
|
|
100
|
-
puts opts
|
|
101
|
-
exit
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
opts.on("-m", "--merb-root MERB_ROOT", "The path to the MERB_ROOT for the app you want to run (default is current working dir).") do |merb_root|
|
|
106
|
-
options[:merb_root] = File.expand_path(merb_root)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
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|
|
|
110
|
-
options[:console] = true
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
opts.on("-s", "--start-drb PORTNUM", "This is the port number to run the drb daemon on for sessions and upload progress monitoring.") do |drb_port|
|
|
114
|
-
options[:start_drb] = true
|
|
115
|
-
options[:only_drb] = true
|
|
116
|
-
options[:drb_server_port] = drb_port
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of these options: DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN") do |loglevel|
|
|
120
|
-
options[:log_level] = loglevel
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
opts.on("-e", "--environment STRING", "Run merb in the correct mode(development, production, testing)") do |env|
|
|
124
|
-
options[:environment] ||= env
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]",
|
|
128
|
-
"Command-line option to run scripts and/or code in the merb app.") do |stuff_to_run|
|
|
129
|
-
options[:runner] = stuff_to_run
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
opts.on("-g", "--generate-app PATH", "Generate a fresh merb app at PATH.") do |path|
|
|
133
|
-
options[:generate] = path || Dir.pwd
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
opts.on("-P","--generate-plugin PATH", "Generate a fresh merb plugin at PATH.") do |path|
|
|
137
|
-
options[:generate_plugin] = path || Dir.pwd
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. Use merb -k all to kill all merbs.") do |ports|
|
|
141
|
-
options[:kill] = ports
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
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|
|
|
145
|
-
options[:graceful] = ports
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
opts.on("-M", "--merb-config FILENAME", "This flag is for explicitly declaring the merb app's config file.") do |config|
|
|
149
|
-
options[:merb_config] = config
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
opts.on("-w", "--webrick", "Run merb using Webrick Rack Adapter instead of mongrel.") do |webport|
|
|
153
|
-
options[:webrick] = true
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
opts.on("-F", "--fastcgi", "Run merb using FastCGI Rack Adapter instead of mongrel.") do
|
|
157
|
-
options[:fastcgi] = true
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
opts.on("-X", "--mutex on/off", "This flag is for turning the mutex lock on and off.") do |mutex|
|
|
161
|
-
if mutex == 'off'
|
|
162
|
-
options[:use_mutex] = false
|
|
163
|
-
else
|
|
164
|
-
options[:use_mutex] = true
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
opts.on("-?", "-H", "--help", "Show this help message") do
|
|
169
|
-
puts opts
|
|
170
|
-
exit
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# Parse what we have on the command line
|
|
175
|
-
opts.parse!(argv)
|
|
176
|
-
|
|
177
|
-
# merb <argument> is same as merb -g <argument>
|
|
178
|
-
if argv.size == 1
|
|
179
|
-
options[:generate] = File.expand_path(argv.last)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
# If we run merb with no arguments and we are not inside a merb root
|
|
183
|
-
# show the help message
|
|
184
|
-
if (argv.size == 0) && !File.exists?("#{options[:merb_root] || Merb::Config.defaults[:merb_root]}/config/merb_init.rb") && !$TESTING
|
|
185
|
-
puts "You are not in the root of a merb application...\n"
|
|
186
|
-
puts opts
|
|
187
|
-
exit
|
|
188
|
-
end
|
|
189
|
-
# Load up the configuration from file, but keep the command line
|
|
190
|
-
# options that may have been chosen. Also, pass-through if we have
|
|
191
|
-
# a new merb_config path.
|
|
192
|
-
options = Merb::Config.setup(options[:merb_config]).merge(options)
|
|
193
|
-
|
|
194
|
-
# Finally, if all else fails... set the environment to 'development'
|
|
195
|
-
options[:environment] ||= 'development'
|
|
196
|
-
|
|
197
|
-
environment_merb_yml = "#{options[:merb_root]}/config/environments/#{options[:environment]}.yml"
|
|
198
|
-
options = Merb::Config.apply_configuration_from_file options, environment_merb_yml
|
|
199
|
-
|
|
200
|
-
@@merb_opts = options
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def max_mtime( files = [] )
|
|
204
|
-
files.map{ |file| File.mtime(file) rescue @mtime }.max
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
def register_session_type(name, file, description = nil)
|
|
208
|
-
@registered_session_types ||= YAML::Omap.new
|
|
209
|
-
@registered_session_types[name] = {
|
|
210
|
-
:file => file,
|
|
211
|
-
:description => (description || "Using #{name} sessions")
|
|
212
|
-
}
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
def add_controller_mixins
|
|
216
|
-
types = @registered_session_types
|
|
217
|
-
Merb::Controller.class_eval do
|
|
218
|
-
lib = File.join(__DIR__, 'merb')
|
|
219
|
-
session_store = Merb::Server.config[:session_store].to_s
|
|
220
|
-
if ["", "false"].include?(session_store)
|
|
221
|
-
puts "Not Using Sessions"
|
|
222
|
-
elsif reg = types[session_store]
|
|
223
|
-
if session_store == "cookie"
|
|
224
|
-
unless @@merb_opts[:session_secret_key] && (@@merb_opts[:session_secret_key].length >= 16)
|
|
225
|
-
puts("You must specify a session_secret_key in your merb.yml, and it must be at least 16 characters\nbailing out...")
|
|
226
|
-
exit!
|
|
227
|
-
end
|
|
228
|
-
Merb::Controller.session_secret_key = @@merb_opts[:session_secret_key]
|
|
229
|
-
end
|
|
230
|
-
require reg[:file]
|
|
231
|
-
include ::Merb::SessionMixin
|
|
232
|
-
puts reg[:description]
|
|
233
|
-
else
|
|
234
|
-
puts "Session store not found, '#{Merb::Server.config[:session_store]}'."
|
|
235
|
-
puts "Defaulting to CookieStore Sessions"
|
|
236
|
-
unless @@merb_opts[:session_secret_key] && (@@merb_opts[:session_secret_key].length >= 16)
|
|
237
|
-
puts("You must specify a session_secret_key in your merb.yml, and it must be at least 16 characters\nbailing out...")
|
|
238
|
-
exit!
|
|
239
|
-
end
|
|
240
|
-
Merb::Controller.session_secret_key = @@merb_opts[:session_secret_key]
|
|
241
|
-
require types['cookie'][:file]
|
|
242
|
-
include ::Merb::SessionMixin
|
|
243
|
-
puts "(plugin not installed?)"
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
if Merb::Server.config[:basic_auth]
|
|
247
|
-
require lib + "/mixins/basic_authentication"
|
|
248
|
-
include ::Merb::AuthenticationMixin
|
|
249
|
-
puts "Basic Authentication mixed in"
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def initialize_merb
|
|
255
|
-
require 'merb'
|
|
256
|
-
@mtime = Time.now if @@merb_opts[:reloader] == true
|
|
257
|
-
# Register session types before merb_init.rb so that any additional
|
|
258
|
-
# session stores will be added to the end of the list and become the
|
|
259
|
-
# default.
|
|
260
|
-
register_session_type('memory',
|
|
261
|
-
__DIR__ / "merb" / "session" / "memory_session",
|
|
262
|
-
"Using in-memory sessions; sessions will be lost whenever the server stops.")
|
|
263
|
-
register_session_type('mem_cache',
|
|
264
|
-
__DIR__ / "merb" / "session" / "mem_cache_session",
|
|
265
|
-
"Using MemCache distributed memory sessions")
|
|
266
|
-
register_session_type('cookie', # Last session type becomes the default
|
|
267
|
-
__DIR__ / "merb" / "session" / "cookie_store",
|
|
268
|
-
"Using 'share-nothing' cookie sessions (4kb limit per client)")
|
|
269
|
-
require @@merb_opts[:merb_root] / 'config/merb_init.rb'
|
|
270
|
-
add_controller_mixins
|
|
271
|
-
end
|
|
272
|
-
|
|
273
|
-
def after_app_loads(&block)
|
|
274
|
-
@after_app_blocks ||= []
|
|
275
|
-
@after_app_blocks << block
|
|
276
|
-
end
|
|
277
|
-
|
|
278
|
-
def app_loaded?
|
|
279
|
-
@app_loaded
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
def load_action_arguments(klasses = Merb::Controller._subclasses)
|
|
283
|
-
begin
|
|
284
|
-
klasses.each do |controller|
|
|
285
|
-
controller = Object.full_const_get(controller)
|
|
286
|
-
controller.action_argument_list = {}
|
|
287
|
-
controller.callable_actions.each do |action, bool|
|
|
288
|
-
controller.action_argument_list[action.to_sym] = ParseTreeArray.translate(controller, action).get_args
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
rescue
|
|
292
|
-
klasses.each { |controller| controller.action_arguments = {} }
|
|
293
|
-
end if defined?(ParseTreeArray)
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
def template_paths(type = "*")
|
|
297
|
-
# This gets all templates set in the controllers template roots
|
|
298
|
-
template_paths = Merb::AbstractController._abstract_subclasses.map do |klass|
|
|
299
|
-
Object.full_const_get(klass)._template_root
|
|
300
|
-
end.uniq.map do |path|
|
|
301
|
-
Dir["#{path}/**/#{type}"]
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
# This gets the templates that might be created outside controllers
|
|
305
|
-
# template roots. eg app/views/shared/*
|
|
306
|
-
template_paths << Dir["#{MERB_ROOT}/app/views/**/*"] if type == "*"
|
|
307
|
-
|
|
308
|
-
template_paths.flatten.compact.uniq || []
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def load_controller_template_path_cache
|
|
312
|
-
Merb::AbstractController.reset_template_path_cache!
|
|
313
|
-
|
|
314
|
-
template_paths.each do |template|
|
|
315
|
-
Merb::AbstractController.add_path_to_template_cache(template)
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def load_erubis_inline_helpers
|
|
320
|
-
partials = template_paths("_*.erb")
|
|
321
|
-
|
|
322
|
-
partials.each do |partial|
|
|
323
|
-
eruby = Erubis::Eruby.new(File.read(partial))
|
|
324
|
-
eruby.def_method(Merb::GlobalHelper, partial.gsub(/[^\.a-zA-Z0-9]/, "__").gsub(/\./, "_"), partial)
|
|
325
|
-
end
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
def load_application
|
|
329
|
-
MERB_PATHS.each do |glob|
|
|
330
|
-
Dir[MERB_ROOT + glob].each { |m| require m }
|
|
331
|
-
end
|
|
332
|
-
load_action_arguments
|
|
333
|
-
load_controller_template_path_cache
|
|
334
|
-
load_erubis_inline_helpers
|
|
335
|
-
@app_loaded = true
|
|
336
|
-
(@after_app_blocks || []).each { |b| b.call }
|
|
337
|
-
end
|
|
338
|
-
|
|
339
|
-
def remove_constant(const)
|
|
340
|
-
parts = const.to_s.split("::")
|
|
341
|
-
base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
|
|
342
|
-
object = parts[-1].intern
|
|
343
|
-
MERB_LOGGER.info("Removing constant #{object} from #{base}")
|
|
344
|
-
base.send(:remove_const, object) if object
|
|
345
|
-
Merb::Controller._subclasses.delete(const)
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
def reload
|
|
349
|
-
return if !@@merb_opts[:reloader] || !Object.const_defined?(:MERB_PATHS)
|
|
350
|
-
|
|
351
|
-
# First we collect all files in the project (this will also grab newly added files)
|
|
352
|
-
project_files = MERB_PATHS.map { |path| Dir[@@merb_opts[:merb_root] + path] }.flatten.uniq
|
|
353
|
-
erb_partials = template_paths("_*.erb").map { |path| Dir[path] }.flatten.uniq
|
|
354
|
-
project_mtime = max_mtime(project_files + erb_partials) # Latest changed time of all project files
|
|
355
|
-
|
|
356
|
-
return if @mtime.nil? || @mtime >= project_mtime # Only continue if a file has changed
|
|
357
|
-
|
|
358
|
-
project_files.each do |file|
|
|
359
|
-
if File.mtime(file) >= @mtime
|
|
360
|
-
# If the file has changed or been added since the last project reload time
|
|
361
|
-
# remove any cannonical constants, based on what type of project file it is
|
|
362
|
-
# and then reload the file
|
|
363
|
-
begin
|
|
364
|
-
constant = case file
|
|
365
|
-
when %r[/app/(models|controllers|parts|mailers)/(.+)\.rb$]
|
|
366
|
-
$2.to_const_string
|
|
367
|
-
when %r[/app/(helpers)/(.+)\.rb$]
|
|
368
|
-
"Merb::" + $2.to_const_string
|
|
369
|
-
end
|
|
370
|
-
remove_constant(constant)
|
|
371
|
-
rescue NameError => e
|
|
372
|
-
MERB_LOGGER.warn "Couldn't remove constant #{constant}"
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
begin
|
|
376
|
-
MERB_LOGGER.info("Reloading file #{file}")
|
|
377
|
-
old_subclasses = Merb::Controller._subclasses.dup
|
|
378
|
-
load(file)
|
|
379
|
-
loaded_classes = Merb::Controller._subclasses - old_subclasses
|
|
380
|
-
load_action_arguments(loaded_classes)
|
|
381
|
-
rescue Exception => e
|
|
382
|
-
puts "Error reloading file #{file}: #{e}"
|
|
383
|
-
MERB_LOGGER.warn " Error: #{e}"
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
# constant = file =~ /\/(controllers|models|mailers|helpers|parts)\/(.*).rb/ ? $2.to_const_string : nil
|
|
387
|
-
# remove_constant($2.to_const_string, ($1 == "helpers") ? Merb : nil)
|
|
388
|
-
# load file and puts "loaded file: #{file}"
|
|
389
|
-
end
|
|
390
|
-
end
|
|
391
|
-
|
|
392
|
-
# Rebuild the glob cache and erubis inline helpers
|
|
393
|
-
load_controller_template_path_cache
|
|
394
|
-
load_erubis_inline_helpers
|
|
395
|
-
|
|
396
|
-
@mtime = project_mtime # As the last action, update the current @mtime
|
|
397
|
-
end
|
|
398
|
-
|
|
399
31
|
def run
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if
|
|
403
|
-
require 'merb/generators/merb_app/merb_app'
|
|
404
|
-
::Merb::AppGenerator.run @@merb_opts[:generate]
|
|
405
|
-
exit!
|
|
406
|
-
end
|
|
407
|
-
|
|
408
|
-
if ENV['EVENT'] || ENV['SWIFT']
|
|
409
|
-
@@merb_opts[:use_mutex] = false
|
|
410
|
-
end
|
|
411
|
-
|
|
412
|
-
if @@merb_opts[:graceful]
|
|
413
|
-
@@merb_opts[:kill] = @@merb_opts[:graceful]
|
|
414
|
-
graceful = true
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
if k = @@merb_opts[:kill]
|
|
418
|
-
begin
|
|
419
|
-
Dir[@@merb_opts[:merb_root] + "/log/merb.#{k == 'all' ? '*' : k }.pid"].each do |f|
|
|
420
|
-
puts f
|
|
421
|
-
pid = IO.read(f).chomp.to_i
|
|
422
|
-
signal = graceful ? 1 : 9
|
|
423
|
-
Process.kill(signal, pid)
|
|
424
|
-
FileUtils.rm f
|
|
425
|
-
puts "killed PID #{pid} with signal #{signal}"
|
|
426
|
-
end
|
|
427
|
-
rescue
|
|
428
|
-
puts "Failed to kill! #{k}"
|
|
429
|
-
ensure
|
|
430
|
-
exit
|
|
431
|
-
end
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
case @@merb_opts[:environment].to_s
|
|
435
|
-
when 'production'
|
|
436
|
-
@@merb_opts[:reloader] = @@merb_opts.fetch(:reloader, false)
|
|
437
|
-
@@merb_opts[:exception_details] = @@merb_opts.fetch(:exception_details, false)
|
|
438
|
-
@@merb_opts[:cache_templates] = true
|
|
439
|
-
else
|
|
440
|
-
@@merb_opts[:reloader] = @@merb_opts.fetch(:reloader, true)
|
|
441
|
-
@@merb_opts[:exception_details] = @@merb_opts.fetch(:exception_details, true)
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
@@merb_opts[:reloader_time] ||= 0.5 if @@merb_opts[:reloader] == true
|
|
445
|
-
|
|
446
|
-
$LOAD_PATH.unshift( File.join(@@merb_opts[:merb_root] , '/app/models') )
|
|
447
|
-
$LOAD_PATH.unshift( File.join(@@merb_opts[:merb_root] , '/app/controllers') )
|
|
448
|
-
$LOAD_PATH.unshift( File.join(@@merb_opts[:merb_root] , '/lib') )
|
|
449
|
-
|
|
450
|
-
if @@merb_opts[:generate_plugin]
|
|
451
|
-
require 'merb/generators/merb_plugin'
|
|
452
|
-
::Merb::PluginGenerator.run @@merb_opts[:generate_plugin]
|
|
453
|
-
exit!
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
if @@merb_opts[:reloader]
|
|
457
|
-
Thread.abort_on_exception = true
|
|
458
|
-
Thread.new do
|
|
459
|
-
loop do
|
|
460
|
-
sleep( @@merb_opts[:reloader_time] )
|
|
461
|
-
reload if app_loaded?
|
|
462
|
-
end
|
|
463
|
-
Thread.exit
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
if @@merb_opts[:console]
|
|
468
|
-
initialize_merb
|
|
469
|
-
_merb = Class.new do
|
|
470
|
-
def self.show_routes(all_opts = false)
|
|
471
|
-
seen = []
|
|
472
|
-
unless Merb::Router.named_routes.empty?
|
|
473
|
-
puts "Named Routes"
|
|
474
|
-
Merb::Router.named_routes.each do |name,route|
|
|
475
|
-
puts " #{name}: #{route}"
|
|
476
|
-
seen << route
|
|
477
|
-
end
|
|
478
|
-
end
|
|
479
|
-
puts "Anonymous Routes"
|
|
480
|
-
(Merb::Router.routes - seen).each do |route|
|
|
481
|
-
puts " #{route}"
|
|
482
|
-
end
|
|
483
|
-
nil
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
def self.url(path, *args)
|
|
487
|
-
Merb::Router.generate(path,*args)
|
|
488
|
-
end
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
Object.send(:define_method, :merb) {
|
|
492
|
-
_merb
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
ARGV.clear # Avoid passing args to IRB
|
|
496
|
-
require 'irb'
|
|
497
|
-
require 'irb/completion'
|
|
498
|
-
def exit
|
|
499
|
-
exit!
|
|
500
|
-
end
|
|
501
|
-
if File.exists? ".irbrc"
|
|
502
|
-
ENV['IRBRC'] = ".irbrc"
|
|
503
|
-
end
|
|
504
|
-
IRB.start
|
|
505
|
-
exit!
|
|
506
|
-
end
|
|
507
|
-
|
|
508
|
-
if @@merb_opts[:runner]
|
|
509
|
-
initialize_merb
|
|
510
|
-
code_or_file = @@merb_opts[:runner]
|
|
511
|
-
if File.exists?(code_or_file)
|
|
512
|
-
eval(File.read(code_or_file))
|
|
513
|
-
else
|
|
514
|
-
eval(code_or_file)
|
|
515
|
-
end
|
|
516
|
-
exit!
|
|
517
|
-
end
|
|
518
|
-
|
|
519
|
-
if @@merb_opts[:start_drb]
|
|
520
|
-
puts "Starting merb drb server on port: #{@@merb_opts[:drb_server_port]}"
|
|
521
|
-
start(@@merb_opts[:drb_server_port], :drbserver_start)
|
|
522
|
-
exit if @@merb_opts[:only_drb]
|
|
523
|
-
end
|
|
524
|
-
|
|
525
|
-
if @@merb_opts[:webrick]
|
|
526
|
-
puts "Starting merb webrick server on port: #{@@merb_opts[:port]}"
|
|
527
|
-
trap('TERM') { exit }
|
|
528
|
-
webrick_start(@@merb_opts[:port])
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
if @@merb_opts[:fastcgi]
|
|
532
|
-
trap('TERM') { exit }
|
|
533
|
-
fastcgi_start
|
|
534
|
-
end
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
if @@merb_opts[:cluster]
|
|
32
|
+
::Merb::Config.parse_args
|
|
33
|
+
|
|
34
|
+
if Merb::Config[:cluster]
|
|
538
35
|
delete_pidfiles
|
|
539
|
-
|
|
36
|
+
Merb::Config[:port].to_i.upto(Merb::Config[:port].to_i+Merb::Config[:cluster].to_i-1) do |port|
|
|
540
37
|
puts "Starting merb server on port: #{port}"
|
|
541
38
|
start(port)
|
|
542
39
|
end
|
|
543
|
-
elsif
|
|
544
|
-
delete_pidfiles(
|
|
545
|
-
start(
|
|
40
|
+
elsif Merb::Config[:daemonize]
|
|
41
|
+
delete_pidfiles(Merb::Config[:port])
|
|
42
|
+
start(Merb::Config[:port])
|
|
546
43
|
else
|
|
547
44
|
trap('TERM') { exit }
|
|
548
|
-
mongrel_start(
|
|
45
|
+
mongrel_start(Merb::Config[:port])
|
|
549
46
|
end
|
|
550
|
-
|
|
47
|
+
|
|
551
48
|
end
|
|
552
49
|
|
|
553
50
|
def store_pid(pid,port)
|
|
554
|
-
File.open("#{
|
|
51
|
+
File.open("#{Merb::Config[:merb_root]}/log/merb.#{port}.pid", 'w'){|f| f.write("#{Process.pid}\n")}
|
|
555
52
|
end
|
|
556
53
|
|
|
54
|
+
def kill(ports, sig=9)
|
|
55
|
+
begin
|
|
56
|
+
Dir[Merb::Config[:merb_root] + "/log/merb.#{ports == 'all' ? '*' : ports }.pid"].each do |f|
|
|
57
|
+
pid = IO.read(f).chomp.to_i
|
|
58
|
+
Process.kill(sig, pid)
|
|
59
|
+
FileUtils.rm f
|
|
60
|
+
puts "killed PID #{pid} with signal #{sig}"
|
|
61
|
+
end
|
|
62
|
+
rescue
|
|
63
|
+
puts "Failed to kill! #{k}"
|
|
64
|
+
ensure
|
|
65
|
+
exit
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
557
69
|
def start(port,what=:mongrel_start)
|
|
558
70
|
fork do
|
|
559
71
|
Process.setsid
|
|
560
72
|
exit if fork
|
|
561
|
-
if what == :mongrel_start
|
|
562
|
-
store_pid(Process.pid, port)
|
|
563
|
-
else
|
|
564
|
-
store_pid(Process.pid, "drb.#{port}")
|
|
565
|
-
end
|
|
566
|
-
Dir.chdir @@merb_opts[:merb_root]
|
|
567
73
|
File.umask 0000
|
|
568
74
|
STDIN.reopen "/dev/null"
|
|
569
75
|
STDOUT.reopen "/dev/null", "a"
|
|
570
76
|
STDERR.reopen STDOUT
|
|
571
77
|
trap("TERM") { exit }
|
|
78
|
+
Dir.chdir Merb::Config[:merb_root]
|
|
572
79
|
send(what, port)
|
|
573
80
|
end
|
|
574
81
|
end
|
|
575
82
|
|
|
576
83
|
def webrick_start(port)
|
|
577
|
-
initialize_merb
|
|
84
|
+
Merb::BootLoader.initialize_merb
|
|
85
|
+
store_pid(Process.pid, port)
|
|
578
86
|
require 'rack'
|
|
579
87
|
require 'merb/rack_adapter'
|
|
580
88
|
::Rack::Handler::WEBrick.run Merb::Rack::Adapter.new,
|
|
@@ -582,63 +90,61 @@ module Merb
|
|
|
582
90
|
end
|
|
583
91
|
|
|
584
92
|
def fastcgi_start
|
|
585
|
-
initialize_merb
|
|
93
|
+
Merb::BootLoader.initialize_merb
|
|
586
94
|
require 'rack'
|
|
587
95
|
require 'merb/rack_adapter'
|
|
588
96
|
::Rack::Handler::FastCGI.run Merb::Rack::Adapter.new
|
|
589
97
|
end
|
|
590
98
|
|
|
591
99
|
def delete_pidfiles(portor_star='*')
|
|
592
|
-
Dir["#{
|
|
100
|
+
Dir["#{Merb::Config[:merb_root]}/log/merb.#{portor_star}.pid"].each do |pid|
|
|
593
101
|
FileUtils.rm(pid) rescue nil
|
|
594
102
|
end
|
|
595
103
|
end
|
|
596
104
|
|
|
597
105
|
def drbserver_start(port)
|
|
598
106
|
puts "Starting merb drb server on port: #{port}"
|
|
599
|
-
require 'merb/
|
|
600
|
-
|
|
107
|
+
require 'merb/drb_server'
|
|
108
|
+
Merb::BootLoader.initialize_merb
|
|
109
|
+
store_pid(Process.pid, "drb.#{port}")
|
|
110
|
+
drb_init = File.join(Merb.root, "/config/drb_init")
|
|
601
111
|
require drb_init if File.exist?(drb_init)
|
|
602
|
-
DRb.start_service("druby://#{
|
|
112
|
+
DRb.start_service("druby://#{Merb::Config[:host]}:#{port}", Merb::DrbServiceProvider)
|
|
603
113
|
DRb.thread.join
|
|
604
114
|
end
|
|
605
115
|
|
|
606
116
|
def mongrel_start(port)
|
|
607
|
-
|
|
608
|
-
|
|
117
|
+
store_pid(Process.pid, port)
|
|
118
|
+
Merb::Config[:port] = port
|
|
119
|
+
unless Merb::Config[:generate] || Merb::Config[:console] || Merb::Config[:only_drb] || Merb::Config[:kill]
|
|
609
120
|
puts %{Merb started with these options:}
|
|
610
|
-
puts
|
|
121
|
+
puts Merb::Config.to_yaml; puts
|
|
611
122
|
end
|
|
612
|
-
initialize_merb
|
|
123
|
+
Merb::BootLoader.initialize_merb
|
|
613
124
|
|
|
614
|
-
mconf_hash = {:host => (
|
|
615
|
-
if
|
|
616
|
-
mconf_hash[:user] =
|
|
617
|
-
mconf_hash[:group] =
|
|
125
|
+
mconf_hash = {:host => (Merb::Config[:host]||"0.0.0.0"), :port => (port ||4000)}
|
|
126
|
+
if Merb::Config[:user] and Merb::Config[:group]
|
|
127
|
+
mconf_hash[:user] = Merb::Config[:user]
|
|
128
|
+
mconf_hash[:group] = Merb::Config[:group]
|
|
618
129
|
end
|
|
619
130
|
mconfig = Mongrel::Configurator.new(mconf_hash) do
|
|
620
131
|
listener do
|
|
621
|
-
uri( "/", :handler => MerbUploadHandler.new(
|
|
622
|
-
uri "/", :handler => MerbHandler.new(
|
|
132
|
+
uri( "/", :handler => MerbUploadHandler.new(Merb::Config), :in_front => true) if Merb::Config[:upload_path_match]
|
|
133
|
+
uri "/", :handler => MerbHandler.new(Merb.root+'/public', Merb::Config[:mongrel_x_sendfile])
|
|
623
134
|
uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("")
|
|
624
135
|
end
|
|
625
|
-
MerbHandler.path_prefix =
|
|
136
|
+
MerbHandler.path_prefix = Merb::Config[:path_prefix]
|
|
626
137
|
|
|
627
138
|
trap("INT") { stop }
|
|
628
139
|
run
|
|
629
140
|
end
|
|
630
141
|
mconfig.join
|
|
631
|
-
end
|
|
142
|
+
end
|
|
632
143
|
|
|
633
144
|
def config
|
|
634
|
-
|
|
145
|
+
Merb::Config
|
|
635
146
|
end
|
|
636
147
|
|
|
637
|
-
def load_config
|
|
638
|
-
@@merb_raw_opts = ARGV
|
|
639
|
-
merb_config
|
|
640
|
-
end
|
|
641
|
-
|
|
642
148
|
end # class << self
|
|
643
149
|
|
|
644
150
|
end # Server
|