merb-core 0.9.9 → 0.9.10
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 +31 -3
- data/Rakefile +2 -2
- data/lib/merb-core.rb +18 -2
- data/lib/merb-core/bootloader.rb +80 -46
- data/lib/merb-core/config.rb +2 -2
- data/lib/merb-core/constants.rb +35 -5
- data/lib/merb-core/controller/abstract_controller.rb +4 -4
- data/lib/merb-core/controller/exceptions.rb +2 -2
- data/lib/merb-core/controller/merb_controller.rb +1 -1
- data/lib/merb-core/dispatch/dispatcher.rb +1 -1
- data/lib/merb-core/dispatch/request.rb +191 -184
- data/lib/merb-core/dispatch/router.rb +62 -27
- data/lib/merb-core/dispatch/router/resources.rb +10 -7
- data/lib/merb-core/dispatch/router/route.rb +2 -0
- data/lib/merb-core/dispatch/session.rb +2 -2
- data/lib/merb-core/rack/adapter/abstract.rb +1 -1
- data/lib/merb-core/tasks/gem_management.rb +15 -3
- data/lib/merb-core/test/helpers/request_helper.rb +4 -0
- data/lib/merb-core/test/tasks/spectasks.rb +10 -0
- data/lib/merb-core/test/test_ext/rspec.rb +0 -5
- data/lib/merb-core/version.rb +1 -1
- metadata +4 -4
data/README
CHANGED
@@ -19,7 +19,35 @@ Goals of this release:
|
|
19
19
|
To familiarize yourself with how a merb-core application might look,
|
20
20
|
use merb-gen (from merb-more) to generate a few apps:
|
21
21
|
|
22
|
-
$ merb-gen app myapp
|
23
|
-
$ merb-gen app myapp --flat # a flattened app
|
24
|
-
$ merb-gen app myapp --very-flat # a single-file app
|
22
|
+
$ merb-gen app myapp # merb stack app, assuming you are using DM and RSpec
|
25
23
|
|
24
|
+
The only option you can use with stack is --template_engine=(erb|haml).
|
25
|
+
Default is erb.
|
26
|
+
|
27
|
+
$ merb-gen core myapp # a "regular" app without any predefined dependencies
|
28
|
+
|
29
|
+
Options available:
|
30
|
+
|
31
|
+
--orm=datamapper
|
32
|
+
--orm=sequel
|
33
|
+
--orm=activerecord
|
34
|
+
|
35
|
+
Default is no ORM.
|
36
|
+
|
37
|
+
--testing_framework=rspec
|
38
|
+
--testing_framework=test_unit
|
39
|
+
|
40
|
+
Default is rspec.
|
41
|
+
|
42
|
+
--template_enging=erb
|
43
|
+
--template_enging=haml
|
44
|
+
|
45
|
+
Default is erb.
|
46
|
+
|
47
|
+
$ merb-gen flat myapp # a flattened app: one file and directory for views
|
48
|
+
|
49
|
+
Options are same as for "regular" app.
|
50
|
+
|
51
|
+
$ merb-gen very_flat myapp # a single-file app
|
52
|
+
|
53
|
+
Options are same as for "regular" app.
|
data/Rakefile
CHANGED
@@ -58,7 +58,7 @@ spec = Gem::Specification.new do |s|
|
|
58
58
|
|
59
59
|
# Dependencies
|
60
60
|
s.add_dependency "extlib", ">= 0.9.8"
|
61
|
-
s.add_dependency "erubis"
|
61
|
+
s.add_dependency "erubis", ">= 2.6.2"
|
62
62
|
s.add_dependency "rake"
|
63
63
|
s.add_dependency "json_pure"
|
64
64
|
s.add_dependency "rspec"
|
@@ -336,7 +336,7 @@ def contributors(since_release = nil)
|
|
336
336
|
git_log(since_release).split("\n").uniq.sort
|
337
337
|
end
|
338
338
|
|
339
|
-
PREVIOUS_RELEASE = '0.9.
|
339
|
+
PREVIOUS_RELEASE = '0.9.9'
|
340
340
|
namespace :history do
|
341
341
|
namespace :update do
|
342
342
|
desc "updates contributors list"
|
data/lib/merb-core.rb
CHANGED
@@ -23,6 +23,8 @@ require "pathname"
|
|
23
23
|
require "extlib"
|
24
24
|
require "extlib/dictionary"
|
25
25
|
|
26
|
+
Thread.abort_on_exception = true
|
27
|
+
|
26
28
|
__DIR__ = File.dirname(__FILE__)
|
27
29
|
|
28
30
|
$LOAD_PATH.unshift __DIR__ unless
|
@@ -275,7 +277,7 @@ module Merb
|
|
275
277
|
#
|
276
278
|
# @api public
|
277
279
|
def root=(value)
|
278
|
-
@root = value
|
280
|
+
@root = File.expand_path(value) + File::SEPARATOR
|
279
281
|
end
|
280
282
|
|
281
283
|
# ==== Parameters
|
@@ -710,7 +712,21 @@ module Merb
|
|
710
712
|
#
|
711
713
|
# @api public
|
712
714
|
def trap(signal, &block)
|
713
|
-
|
715
|
+
if Signal.list.include?(signal)
|
716
|
+
Kernel.trap(signal, &block) unless Merb.disabled?(:signals)
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
def forking_environment?
|
721
|
+
!on_windows? && !on_jruby?
|
722
|
+
end
|
723
|
+
|
724
|
+
def on_jruby?
|
725
|
+
RUBY_PLATFORM =~ Merb::Const::JAVA_PLATFORM_REGEXP
|
726
|
+
end
|
727
|
+
|
728
|
+
def on_windows?
|
729
|
+
RUBY_PLATFORM =~ Merb::Const::WIN_PLATFORM_REGEXP
|
714
730
|
end
|
715
731
|
|
716
732
|
end
|
data/lib/merb-core/bootloader.rb
CHANGED
@@ -5,9 +5,12 @@ module Merb
|
|
5
5
|
# def self.subclasses
|
6
6
|
#
|
7
7
|
# @api plugin
|
8
|
-
cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks,
|
8
|
+
cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks,
|
9
|
+
:finished, :before_worker_shutdown_callbacks, :before_master_shutdown_callbacks
|
10
|
+
|
9
11
|
self.subclasses, self.after_load_callbacks,
|
10
|
-
self.before_load_callbacks, self.finished
|
12
|
+
self.before_load_callbacks, self.finished, self.before_master_shutdown_callbacks,
|
13
|
+
self.before_worker_shutdown_callbacks = [], [], [], [], [], []
|
11
14
|
|
12
15
|
class << self
|
13
16
|
|
@@ -34,7 +37,7 @@ module Merb
|
|
34
37
|
#
|
35
38
|
# ==== Returns
|
36
39
|
# nil
|
37
|
-
#
|
40
|
+
#
|
38
41
|
# @api plugin
|
39
42
|
def after(klass)
|
40
43
|
move_klass(klass, 1)
|
@@ -131,7 +134,7 @@ module Merb
|
|
131
134
|
Merb.push_path(:config, Merb.root_path("config"), nil)
|
132
135
|
Merb.push_path(:router, Merb.dir_for(:config), (Merb::Config[:router_file] || "router.rb"))
|
133
136
|
Merb.push_path(:lib, Merb.root_path("lib"), nil)
|
134
|
-
Merb.push_path(:
|
137
|
+
Merb.push_path(:merb_session, Merb.root_path("merb" / "session"))
|
135
138
|
Merb.push_path(:log, Merb.log_path, nil)
|
136
139
|
Merb.push_path(:public, Merb.root_path("public"), nil)
|
137
140
|
Merb.push_path(:stylesheet, Merb.dir_for(:public) / "stylesheets", nil)
|
@@ -163,6 +166,14 @@ module Merb
|
|
163
166
|
def before_app_loads(&block)
|
164
167
|
before_load_callbacks << block
|
165
168
|
end
|
169
|
+
|
170
|
+
def before_master_shutdown(&block)
|
171
|
+
before_master_shutdown_callbacks << block
|
172
|
+
end
|
173
|
+
|
174
|
+
def before_worker_shutdown(&block)
|
175
|
+
before_worker_shutdown_callbacks << block
|
176
|
+
end
|
166
177
|
end
|
167
178
|
|
168
179
|
end
|
@@ -193,7 +204,7 @@ class Merb::BootLoader::Logger < Merb::BootLoader
|
|
193
204
|
Merb::Config[:log_stream] = Merb.log_stream
|
194
205
|
|
195
206
|
print_warnings
|
196
|
-
|
207
|
+
|
197
208
|
nil
|
198
209
|
end
|
199
210
|
|
@@ -234,10 +245,10 @@ end
|
|
234
245
|
# Setup some useful defaults
|
235
246
|
class Merb::BootLoader::Defaults < Merb::BootLoader
|
236
247
|
# Sets up the defaults
|
237
|
-
#
|
248
|
+
#
|
238
249
|
# ==== Returns
|
239
250
|
# nil
|
240
|
-
#
|
251
|
+
#
|
241
252
|
# @api plugin
|
242
253
|
def self.run
|
243
254
|
Merb::Request.http_method_overrides.concat([
|
@@ -352,7 +363,7 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
352
363
|
# then environment init file, then start enabling specific
|
353
364
|
# components, load dependencies and update logger.
|
354
365
|
unless Merb::disabled?(:initfile)
|
355
|
-
load_initfile
|
366
|
+
load_initfile
|
356
367
|
load_env_config
|
357
368
|
end
|
358
369
|
enable_json_gem unless Merb::disabled?(:json)
|
@@ -362,7 +373,7 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
362
373
|
end
|
363
374
|
|
364
375
|
# Load each dependency that has been declared so far.
|
365
|
-
#
|
376
|
+
#
|
366
377
|
# ==== Returns
|
367
378
|
# nil
|
368
379
|
#
|
@@ -384,7 +395,7 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
384
395
|
require "json/pure"
|
385
396
|
end
|
386
397
|
|
387
|
-
# Resets the logger and sets the log_stream to Merb::Config[:log_file]
|
398
|
+
# Resets the logger and sets the log_stream to Merb::Config[:log_file]
|
388
399
|
# if one is specified, falling back to STDOUT.
|
389
400
|
#
|
390
401
|
# ==== Returns
|
@@ -403,7 +414,7 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
|
|
403
414
|
else
|
404
415
|
Merb::Config[:log_stream] ||= STDOUT
|
405
416
|
end
|
406
|
-
|
417
|
+
|
407
418
|
nil
|
408
419
|
end
|
409
420
|
|
@@ -589,7 +600,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
589
600
|
end
|
590
601
|
|
591
602
|
Merb::Controller.send :include, Merb::GlobalHelpers
|
592
|
-
|
603
|
+
|
593
604
|
nil
|
594
605
|
end
|
595
606
|
|
@@ -607,14 +618,22 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
607
618
|
Merb::Server.remove_pid("main")
|
608
619
|
# terminate, workers remove their own pids
|
609
620
|
# in on exit hook
|
621
|
+
|
622
|
+
Merb::BootLoader.before_master_shutdown_callbacks.each do |cb|
|
623
|
+
begin
|
624
|
+
cb.call
|
625
|
+
rescue Exception => e
|
626
|
+
Merb.logger.fatal "before_master_shutdown callback crashed: #{e.message}"
|
627
|
+
end
|
628
|
+
end
|
610
629
|
exit
|
611
630
|
end
|
612
631
|
|
613
|
-
# Set up the BEGIN point for fork-based loading and sets up
|
632
|
+
# Set up the BEGIN point for fork-based loading and sets up
|
614
633
|
# any signals in the parent and child. This is done by forking
|
615
634
|
# the app. The child process continues on to run the app. The parent
|
616
635
|
# process waits for the child process to finish and either forks again
|
617
|
-
#
|
636
|
+
#
|
618
637
|
#
|
619
638
|
# ==== Returns
|
620
639
|
# Parent Process:
|
@@ -668,7 +687,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
668
687
|
reader_ary = [reader]
|
669
688
|
loop do
|
670
689
|
# wait for worker to exit and capture exit status
|
671
|
-
#
|
690
|
+
#
|
672
691
|
#
|
673
692
|
# WNOHANG specifies that wait2 exists without waiting
|
674
693
|
# if no worker processes are ready to be noticed.
|
@@ -705,13 +724,13 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
705
724
|
Merb::Server.add_irb_trap
|
706
725
|
at_exit { reap_workers }
|
707
726
|
else
|
708
|
-
Merb.trap('INT') {}
|
727
|
+
Merb.trap('INT') { Merb::BootLoader.before_worker_shutdown_callbacks.each { |cb| cb.call } }
|
709
728
|
Merb.trap('ABRT') { reap_workers }
|
710
729
|
Merb.trap('HUP') { reap_workers(128) }
|
711
730
|
end
|
712
731
|
end
|
713
732
|
|
714
|
-
# Reap any workers of the spawner process and
|
733
|
+
# Reap any workers of the spawner process and
|
715
734
|
# exit with an appropriate status code.
|
716
735
|
#
|
717
736
|
# Note that exiting the spawner process with a status code
|
@@ -728,6 +747,16 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
728
747
|
# @param status<Integer> The status code to exit with
|
729
748
|
# @param sig<String> The signal to send to workers
|
730
749
|
def reap_workers(status = 0, sig = "ABRT")
|
750
|
+
Merb.logger.info "Executed all before worker shutdown callbacks..."
|
751
|
+
Merb::BootLoader.before_worker_shutdown_callbacks.each do |cb|
|
752
|
+
begin
|
753
|
+
cb.call
|
754
|
+
rescue Exception => e
|
755
|
+
Merb.logger.fatal "before worker shutdown callback crashed: #{e.message}"
|
756
|
+
end
|
757
|
+
|
758
|
+
end
|
759
|
+
|
731
760
|
Merb.exiting = true unless status == 128
|
732
761
|
|
733
762
|
begin
|
@@ -781,7 +810,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
781
810
|
unless Merb::Config[:fork_for_class_load]
|
782
811
|
LOADED_CLASSES[file] = ObjectSpace.classes - klasses
|
783
812
|
end
|
784
|
-
|
813
|
+
|
785
814
|
nil
|
786
815
|
end
|
787
816
|
|
@@ -808,7 +837,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
808
837
|
end
|
809
838
|
load_classes_with_requirements(orphaned_classes)
|
810
839
|
end
|
811
|
-
|
840
|
+
|
812
841
|
# Reloads the classes in the specified file. If fork-based loading is used,
|
813
842
|
# this causes the current processes to be killed and and all classes to be
|
814
843
|
# reloaded. If class-based loading is not in use, the classes declared in that file
|
@@ -856,7 +885,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
856
885
|
nil
|
857
886
|
end
|
858
887
|
|
859
|
-
# Removes the specified class.
|
888
|
+
# Removes the specified class.
|
860
889
|
#
|
861
890
|
# Additionally, removes the specified class from the subclass list of every superclass that
|
862
891
|
# tracks it's subclasses in an array returned by _subclasses_list. Classes that wish to use this
|
@@ -943,7 +972,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
|
|
943
972
|
end
|
944
973
|
break if(klasses.size == size_at_start || klasses.size == 0)
|
945
974
|
end
|
946
|
-
|
975
|
+
|
947
976
|
nil
|
948
977
|
end
|
949
978
|
|
@@ -955,7 +984,7 @@ end
|
|
955
984
|
# the router has everything it needs to run.
|
956
985
|
class Merb::BootLoader::Router < Merb::BootLoader
|
957
986
|
class << self
|
958
|
-
|
987
|
+
|
959
988
|
# load the router file
|
960
989
|
#
|
961
990
|
# ==== Returns
|
@@ -964,7 +993,7 @@ class Merb::BootLoader::Router < Merb::BootLoader
|
|
964
993
|
# @api plugin
|
965
994
|
def run
|
966
995
|
Merb::BootLoader::LoadClasses.load_file(router_file) if router_file
|
967
|
-
|
996
|
+
|
968
997
|
nil
|
969
998
|
end
|
970
999
|
|
@@ -1110,29 +1139,20 @@ class Merb::BootLoader::SetupSession < Merb::BootLoader
|
|
1110
1139
|
end
|
1111
1140
|
|
1112
1141
|
# Mixin the Merb::Session module to add app-level functionality to sessions
|
1142
|
+
overrides = (Merb::Session.instance_methods & Merb::SessionContainer.instance_methods)
|
1143
|
+
overrides.each do |m|
|
1144
|
+
Merb.logger.warn!("Warning: Merb::Session##{m} overrides existing " \
|
1145
|
+
"Merb::SessionContainer##{m}")
|
1146
|
+
end
|
1113
1147
|
Merb::SessionContainer.send(:include, Merb::Session)
|
1114
1148
|
nil
|
1115
1149
|
end
|
1116
1150
|
|
1117
1151
|
end
|
1118
1152
|
|
1119
|
-
class Merb::BootLoader::AfterAppLoads < Merb::BootLoader
|
1120
|
-
|
1121
|
-
# Call any after_app_loads hooks that were registered via after_app_loads in
|
1122
|
-
# init.rb.
|
1123
|
-
#
|
1124
|
-
# ==== Returns
|
1125
|
-
# nil
|
1126
|
-
#
|
1127
|
-
# @api plugin
|
1128
|
-
def self.run
|
1129
|
-
Merb::BootLoader.after_load_callbacks.each {|x| x.call }
|
1130
|
-
nil
|
1131
|
-
end
|
1132
|
-
end
|
1133
|
-
|
1134
1153
|
# In case someone's running a sparse app, the default exceptions require the
|
1135
|
-
# Exceptions class.
|
1154
|
+
# Exceptions class. This must run prior to the AfterAppLoads BootLoader
|
1155
|
+
# So that plugins may have ensured access in the after_app_loads block
|
1136
1156
|
class Merb::BootLoader::SetupStubClasses < Merb::BootLoader
|
1137
1157
|
# Declares empty Application and Exception controllers.
|
1138
1158
|
#
|
@@ -1147,7 +1167,7 @@ class Merb::BootLoader::SetupStubClasses < Merb::BootLoader
|
|
1147
1167
|
abstract!
|
1148
1168
|
end
|
1149
1169
|
|
1150
|
-
class Exceptions <
|
1170
|
+
class Exceptions < Merb::Controller
|
1151
1171
|
end
|
1152
1172
|
RUBY
|
1153
1173
|
end
|
@@ -1155,6 +1175,21 @@ class Merb::BootLoader::SetupStubClasses < Merb::BootLoader
|
|
1155
1175
|
end
|
1156
1176
|
end
|
1157
1177
|
|
1178
|
+
class Merb::BootLoader::AfterAppLoads < Merb::BootLoader
|
1179
|
+
|
1180
|
+
# Call any after_app_loads hooks that were registered via after_app_loads in
|
1181
|
+
# init.rb.
|
1182
|
+
#
|
1183
|
+
# ==== Returns
|
1184
|
+
# nil
|
1185
|
+
#
|
1186
|
+
# @api plugin
|
1187
|
+
def self.run
|
1188
|
+
Merb::BootLoader.after_load_callbacks.each {|x| x.call }
|
1189
|
+
nil
|
1190
|
+
end
|
1191
|
+
end
|
1192
|
+
|
1158
1193
|
class Merb::BootLoader::ChooseAdapter < Merb::BootLoader
|
1159
1194
|
|
1160
1195
|
# Choose the Rack adapter/server to use and set Merb.adapter.
|
@@ -1197,7 +1232,7 @@ class Merb::BootLoader::RackUpApplication < Merb::BootLoader
|
|
1197
1232
|
run Merb::Rack::Application.new
|
1198
1233
|
}.to_app
|
1199
1234
|
end
|
1200
|
-
|
1235
|
+
|
1201
1236
|
nil
|
1202
1237
|
end
|
1203
1238
|
end
|
@@ -1216,7 +1251,6 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
|
|
1216
1251
|
#
|
1217
1252
|
# @api private
|
1218
1253
|
def self.every(seconds, &block)
|
1219
|
-
Thread.abort_on_exception = true
|
1220
1254
|
Thread.new do
|
1221
1255
|
loop do
|
1222
1256
|
sleep( seconds )
|
@@ -1227,10 +1261,10 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
|
|
1227
1261
|
end
|
1228
1262
|
end
|
1229
1263
|
|
1230
|
-
# Set up the class reloader if class reloading is enabled. This checks periodically
|
1264
|
+
# Set up the class reloader if class reloading is enabled. This checks periodically
|
1231
1265
|
# for modifications to files loaded by the LoadClasses BootLoader and reloads them
|
1232
1266
|
# when they are modified.
|
1233
|
-
#
|
1267
|
+
#
|
1234
1268
|
# ==== Returns
|
1235
1269
|
# nil
|
1236
1270
|
#
|
@@ -1255,7 +1289,7 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
|
|
1255
1289
|
GC.start
|
1256
1290
|
reload(paths)
|
1257
1291
|
end
|
1258
|
-
|
1292
|
+
|
1259
1293
|
nil
|
1260
1294
|
end
|
1261
1295
|
|
@@ -1272,7 +1306,7 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
|
|
1272
1306
|
|
1273
1307
|
LoadClasses.reload(file)
|
1274
1308
|
end
|
1275
|
-
|
1309
|
+
|
1276
1310
|
nil
|
1277
1311
|
end
|
1278
1312
|
end
|
data/lib/merb-core/config.rb
CHANGED
@@ -18,7 +18,7 @@ module Merb
|
|
18
18
|
:port => "4000",
|
19
19
|
:adapter => "runner",
|
20
20
|
:reload_classes => true,
|
21
|
-
:fork_for_class_load =>
|
21
|
+
:fork_for_class_load => Merb.forking_environment?,
|
22
22
|
:environment => "development",
|
23
23
|
:merb_root => Dir.pwd,
|
24
24
|
:use_mutex => true,
|
@@ -26,7 +26,7 @@ module Merb
|
|
26
26
|
:log_auto_flush => false,
|
27
27
|
:log_level => :info,
|
28
28
|
:log_stream => STDOUT,
|
29
|
-
:disabled_components => [],
|
29
|
+
:disabled_components => Merb.on_windows? ? [:signals] : [],
|
30
30
|
:deferred_actions => [],
|
31
31
|
:verbose => false,
|
32
32
|
:name => "merb"
|