wycats-merb-core 0.9.8 → 0.9.9

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.
Files changed (58) hide show
  1. data/CHANGELOG +136 -2
  2. data/CONTRIBUTORS +6 -0
  3. data/PUBLIC_CHANGELOG +15 -0
  4. data/Rakefile +12 -14
  5. data/lib/merb-core.rb +82 -43
  6. data/lib/merb-core/bootloader.rb +268 -60
  7. data/lib/merb-core/config.rb +119 -34
  8. data/lib/merb-core/controller/abstract_controller.rb +58 -18
  9. data/lib/merb-core/controller/exceptions.rb +2 -15
  10. data/lib/merb-core/controller/merb_controller.rb +28 -1
  11. data/lib/merb-core/controller/mime.rb +4 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +14 -17
  13. data/lib/merb-core/controller/mixins/render.rb +23 -28
  14. data/lib/merb-core/controller/mixins/responder.rb +0 -1
  15. data/lib/merb-core/controller/template.rb +44 -20
  16. data/lib/merb-core/core_ext/kernel.rb +8 -3
  17. data/lib/merb-core/dispatch/default_exception/default_exception.rb +1 -1
  18. data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +3 -1
  19. data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +71 -67
  20. data/lib/merb-core/dispatch/default_exception/views/index.html.erb +6 -2
  21. data/lib/merb-core/dispatch/dispatcher.rb +5 -9
  22. data/lib/merb-core/dispatch/request.rb +46 -57
  23. data/lib/merb-core/dispatch/router.rb +83 -6
  24. data/lib/merb-core/dispatch/router/behavior.rb +87 -27
  25. data/lib/merb-core/dispatch/router/resources.rb +281 -167
  26. data/lib/merb-core/dispatch/router/route.rb +141 -27
  27. data/lib/merb-core/logger.rb +213 -202
  28. data/lib/merb-core/rack.rb +3 -1
  29. data/lib/merb-core/rack/adapter.rb +7 -4
  30. data/lib/merb-core/rack/adapter/ebb.rb +12 -13
  31. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -15
  32. data/lib/merb-core/rack/adapter/irb.rb +3 -2
  33. data/lib/merb-core/rack/adapter/mongrel.rb +22 -15
  34. data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +4 -16
  35. data/lib/merb-core/rack/adapter/thin.rb +21 -22
  36. data/lib/merb-core/rack/adapter/thin_turbo.rb +4 -11
  37. data/lib/merb-core/rack/adapter/webrick.rb +54 -18
  38. data/lib/merb-core/rack/handler/mongrel.rb +12 -13
  39. data/lib/merb-core/rack/middleware/csrf.rb +1 -1
  40. data/lib/merb-core/server.rb +135 -98
  41. data/lib/merb-core/tasks/gem_management.rb +50 -12
  42. data/lib/merb-core/tasks/merb.rb +1 -0
  43. data/lib/merb-core/tasks/merb_rake_helper.rb +9 -38
  44. data/lib/merb-core/tasks/stats.rake +2 -2
  45. data/lib/merb-core/test.rb +9 -3
  46. data/lib/merb-core/test/helpers.rb +1 -0
  47. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -2
  48. data/lib/merb-core/test/helpers/request_helper.rb +40 -372
  49. data/lib/merb-core/test/helpers/route_helper.rb +15 -7
  50. data/lib/merb-core/test/matchers.rb +1 -0
  51. data/lib/merb-core/test/matchers/controller_matchers.rb +4 -247
  52. data/lib/merb-core/test/matchers/view_matchers.rb +22 -4
  53. data/lib/merb-core/test/run_specs.rb +117 -25
  54. data/lib/merb-core/version.rb +1 -1
  55. metadata +1 -1
  56. data/lib/merb-core/vendor/facets.rb +0 -2
  57. data/lib/merb-core/vendor/facets/dictionary.rb +0 -433
  58. data/lib/merb-core/vendor/facets/inflect.rb +0 -342
@@ -6,7 +6,8 @@ module Merb
6
6
  #---
7
7
  # @semipublic
8
8
  cattr_accessor :subclasses, :after_load_callbacks, :before_load_callbacks, :finished
9
- self.subclasses, self.after_load_callbacks, self.before_load_callbacks, self.finished = [], [], [], []
9
+ self.subclasses, self.after_load_callbacks,
10
+ self.before_load_callbacks, self.finished = [], [], [], []
10
11
 
11
12
  class << self
12
13
 
@@ -74,7 +75,7 @@ module Merb
74
75
  end
75
76
  self.subclasses = subklasses
76
77
  end
77
-
78
+
78
79
  # Determines whether or not a specific bootloader has finished yet.
79
80
  #
80
81
  # ==== Parameters
@@ -144,13 +145,23 @@ class Merb::BootLoader::Logger < Merb::BootLoader
144
145
 
145
146
  # Sets Merb.logger to a new logger created based on the config settings.
146
147
  def self.run
147
- Merb.logger = Merb::Logger.new(Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush])
148
+ Merb::Config[:log_level] ||= begin
149
+ if Merb.environment == "production"
150
+ Merb::Logger::Levels[:warn]
151
+ else
152
+ Merb::Logger::Levels[:debug]
153
+ end
154
+ end
155
+
156
+ Merb::Config[:log_stream] = Merb.log_stream
157
+
148
158
  print_warnings
149
159
  end
150
-
160
+
151
161
  def self.print_warnings
152
162
  if Gem::Version.new(Gem::RubyGemsVersion) < Gem::Version.new("1.1")
153
- Merb.logger.warn! "Merb requires Rubygems 1.1 and later. Please upgrade RubyGems with gem update --system."
163
+ Merb.fatal! "Merb requires Rubygems 1.1 and later. " \
164
+ "Please upgrade RubyGems with gem update --system."
154
165
  end
155
166
  end
156
167
  end
@@ -159,12 +170,12 @@ end
159
170
  #
160
171
  # Only run if daemonization or clustering options specified on start.
161
172
  # Port is taken from Merb::Config and must be already set at this point.
162
- class Merb::BootLoader::DropPidFile < Merb::BootLoader
173
+ class Merb::BootLoader::DropPidFile < Merb::BootLoader
163
174
  class << self
164
175
 
165
176
  # Stores a PID file if Merb is running daemonized or clustered.
166
177
  def run
167
- Merb::Server.store_pid(Merb::Config[:port]) if Merb::Config[:daemonize] || Merb::Config[:cluster]
178
+ Merb::Server.store_pid("main") #if Merb::Config[:daemonize] || Merb::Config[:cluster]
168
179
  end
169
180
  end
170
181
  end
@@ -257,6 +268,10 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
257
268
  # haven't been loaded up until this point.
258
269
 
259
270
  def self.run
271
+ set_encoding
272
+ # this is crucial: load init file with all the preferences
273
+ # then environment init file, then start enabling specific
274
+ # components, load dependencies and update logger.
260
275
  load_initfile
261
276
  load_env_config
262
277
  enable_json_gem unless Merb::disabled?(:json)
@@ -269,14 +284,29 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
269
284
  end
270
285
 
271
286
  def self.enable_json_gem
287
+ gem "json"
272
288
  require "json/ext"
273
289
  rescue LoadError
290
+ gem "json_pure"
274
291
  require "json/pure"
275
292
  end
276
293
 
277
294
  def self.update_logger
278
- updated_logger_options = [ Merb.log_file, Merb::Config[:log_level], Merb::Config[:log_delimiter], Merb::Config[:log_auto_flush] ]
279
- Merb::BootLoader::Logger.run if updated_logger_options != Merb.logger.init_args
295
+ Merb.logger = nil
296
+
297
+ # If log file is given, use it and not log stream we have.
298
+ if Merb::Config[:log_file]
299
+ raise "log file should be a string, got: #{Merb::Config[:log_file].inspect}" unless Merb::Config[:log_file].is_a?(String)
300
+ STDOUT.puts "Logging to file at #{Merb::Config[:log_file]}" unless Merb.testing?
301
+ Merb::Config[:log_stream] = File.open(Merb::Config[:log_file], "w+")
302
+ # but if it's not given, fallback to log stream or stdout
303
+ else
304
+ Merb::Config[:log_stream] ||= STDOUT
305
+ end
306
+ end
307
+
308
+ def self.set_encoding
309
+ $KCODE = 'UTF8' if $KCODE == 'NONE' || $KCODE.blank?
280
310
  end
281
311
 
282
312
  private
@@ -293,7 +323,10 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
293
323
 
294
324
  # Loads the environment configuration file, if any
295
325
  def self.load_env_config
296
- load(env_config) if env_config?
326
+ if env_config?
327
+ STDOUT.puts "Loading #{env_config}" unless Merb.testing?
328
+ load(env_config)
329
+ end
297
330
  end
298
331
 
299
332
  # Determines the init file to use, if any.
@@ -308,9 +341,11 @@ class Merb::BootLoader::Dependencies < Merb::BootLoader
308
341
 
309
342
  # Loads the init file, should one exist
310
343
  def self.load_initfile
311
- load(initfile) if File.exists?(initfile)
344
+ if File.exists?(initfile)
345
+ STDOUT.puts "Loading init file from #{initfile}" unless Merb.testing?
346
+ load(initfile)
347
+ end
312
348
  end
313
-
314
349
  end
315
350
 
316
351
  class Merb::BootLoader::MixinSession < Merb::BootLoader
@@ -320,7 +355,7 @@ class Merb::BootLoader::MixinSession < Merb::BootLoader
320
355
  # plugin session stores for example - these need to be loaded in a
321
356
  # before_app_loads block or a BootLoader that runs after MixinSession.
322
357
  #
323
- # Note: access to Merb::Config is needed, so it needs to run after
358
+ # Note: access to Merb::Config is needed, so it needs to run after
324
359
  # Merb::BootLoader::Dependencies is done.
325
360
  def self.run
326
361
  require 'merb-core/dispatch/session'
@@ -356,32 +391,174 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
356
391
  # Load all classes from Merb's native load paths.
357
392
  def run
358
393
  # Add models, controllers, helpers and lib to the load path
359
- $LOAD_PATH.unshift Merb.dir_for(:model)
360
- $LOAD_PATH.unshift Merb.dir_for(:controller)
361
- $LOAD_PATH.unshift Merb.dir_for(:lib)
362
- $LOAD_PATH.unshift Merb.dir_for(:helper)
394
+ unless @ran
395
+ $LOAD_PATH.unshift Merb.dir_for(:model)
396
+ $LOAD_PATH.unshift Merb.dir_for(:controller)
397
+ $LOAD_PATH.unshift Merb.dir_for(:lib)
398
+ $LOAD_PATH.unshift Merb.dir_for(:helper)
399
+ end
400
+
401
+ @ran = true
402
+ $0 = "merb#{" : " + Merb::Config[:name] if Merb::Config[:name]} : master"
403
+
404
+ if Merb::Config[:fork_for_class_load] && !Merb.testing?
405
+ start_transaction
406
+ else
407
+ Merb.trap('INT') do
408
+ Merb.logger.warn! "Killing children"
409
+ kill_children
410
+ end
411
+ end
363
412
 
364
413
  # Load application file if it exists - for flat applications
365
414
  load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application))
366
-
415
+
367
416
  # Load classes and their requirements
368
417
  Merb.load_paths.each do |component, path|
369
- next unless path.last && component != :application
418
+ next if path.last.blank? || component == :application || component == :router
370
419
  load_classes(path.first / path.last)
371
420
  end
372
421
 
373
422
  Merb::Controller.send :include, Merb::GlobalHelpers
374
423
  end
375
-
424
+
425
+ # Wait for any children to exit, remove the "main" PID, and
426
+ # exit.
427
+ def exit_gracefully
428
+ Process.waitall
429
+ Merb::Server.remove_pid("main")
430
+ exit
431
+ end
432
+
433
+ # If using fork-based code reloading, set up the BEGIN
434
+ # point and set up any signals in the parent and child.
435
+ def start_transaction
436
+ Merb.logger.warn! "Parent pid: #{Process.pid}"
437
+ reader, writer = nil, nil
438
+
439
+ if GC.respond_to?(:copy_on_write_friendly=)
440
+ GC.copy_on_write_friendly = true
441
+ end
442
+
443
+ loop do
444
+ reader, @writer = IO.pipe
445
+ pid = Kernel.fork
446
+
447
+ # pid means we're in the parent; only stay in the loop in that case
448
+ break unless pid
449
+ @writer.close
450
+
451
+ Merb::Server.store_pid("main")
452
+
453
+ if Merb::Config[:console_trap]
454
+ Merb.trap("INT") {}
455
+ else
456
+ Merb.trap("INT") do
457
+ Merb.logger.warn! "Killing children"
458
+ begin
459
+ Process.kill("ABRT", pid)
460
+ rescue SystemCallError
461
+ end
462
+ exit_gracefully
463
+ end
464
+ end
465
+
466
+ Merb.trap("HUP") do
467
+ Merb.logger.warn! "Doing a fast deploy\n"
468
+ Process.kill("HUP", pid)
469
+ end
470
+
471
+ reader_ary = [reader]
472
+ loop do
473
+ if exit_status = Process.wait2(pid, Process::WNOHANG)
474
+ exit_status[1] == 128 ? break : exit
475
+ end
476
+ if select(reader_ary, nil, nil, 0.25)
477
+ begin
478
+ next if reader.eof?
479
+ msg = reader.readline
480
+ if msg =~ /128/
481
+ break
482
+ else
483
+ exit_gracefully
484
+ end
485
+ rescue SystemCallError
486
+ exit_gracefully
487
+ end
488
+ end
489
+ end
490
+ end
491
+
492
+ reader.close
493
+
494
+ # add traps to the child
495
+ if Merb::Config[:console_trap]
496
+ Merb::Server.add_irb_trap
497
+ at_exit { kill_children }
498
+ else
499
+ Merb.trap('INT') {}
500
+ Merb.trap('ABRT') { kill_children }
501
+ Merb.trap('HUP') { kill_children(128) }
502
+ end
503
+ end
504
+
505
+ # Kill any children of the spawner process and exit with
506
+ # an appropriate status code.
507
+ #
508
+ # Note that exiting the spawner process with a status code
509
+ # of 128 when a master process exists will cause the
510
+ # spawner process to be recreated, and the app code reloaded.
511
+ #
512
+ # @param status<Integer> The status code to exit with
513
+ def kill_children(status = 0)
514
+ Merb.exiting = true unless status == 128
515
+
516
+ begin
517
+ @writer.puts(status.to_s) if @writer
518
+ rescue SystemCallError
519
+ end
520
+
521
+ threads = []
522
+
523
+ ($CHILDREN || []).each do |p|
524
+ threads << Thread.new do
525
+ begin
526
+ Process.kill("ABRT", p)
527
+ Process.wait2(p)
528
+ rescue SystemCallError
529
+ end
530
+ end
531
+ end
532
+ threads.each {|t| t.join }
533
+ exit(status)
534
+ end
535
+
376
536
  # ==== Parameters
377
537
  # file<String>:: The file to load.
378
538
  def load_file(file)
379
- klasses = ObjectSpace.classes.dup
380
- load file
381
- LOADED_CLASSES[file] = ObjectSpace.classes - klasses
382
- MTIMES[file] = File.mtime(file)
539
+ # Don't do this expensive operation unless we need to
540
+ unless Merb::Config[:fork_for_class_load]
541
+ klasses = ObjectSpace.classes.dup
542
+ end
543
+
544
+ # Ignore the file for syntax errors. The next time
545
+ # the file is changed, it'll be reloaded again
546
+ begin
547
+ load file
548
+ rescue SyntaxError
549
+ return
550
+ ensure
551
+ if Merb::Config[:reload_classes]
552
+ MTIMES[file] = File.mtime(file)
553
+ end
554
+ end
555
+
556
+ # Don't do this expensive operation unless we need to
557
+ unless Merb::Config[:fork_for_class_load]
558
+ LOADED_CLASSES[file] = ObjectSpace.classes - klasses
559
+ end
383
560
  end
384
-
561
+
385
562
  # Load classes from given paths - using path/glob pattern.
386
563
  #
387
564
  # *paths<Array>::
@@ -403,22 +580,18 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
403
580
  # ==== Parameters
404
581
  # file<String>:: The file to reload.
405
582
  def reload(file)
406
- remove_classes_in_file(file) { |f| load_file(f) }
407
- end
408
-
409
- # Reload the router to regenerate all routes.
410
- def reload_router!
411
- if File.file?(router_file = Merb.dir_for(:router) / Merb.glob_for(:router))
412
- Merb::Router.reset!
413
- reload router_file
583
+ if Merb::Config[:fork_for_class_load]
584
+ kill_children(128)
585
+ else
586
+ remove_classes_in_file(file) { |f| load_file(f) }
414
587
  end
415
588
  end
416
-
589
+
417
590
  # ==== Parameters
418
591
  # file<String>:: The file to remove classes for.
419
592
  # &block:: A block to call with the file that has been removed.
420
593
  def remove_classes_in_file(file, &block)
421
- Merb.klass_hashes.each {|x| x.protect_keys!}
594
+ Merb.klass_hashes.each { |x| x.protect_keys! }
422
595
  if klasses = LOADED_CLASSES.delete(file)
423
596
  klasses.each { |klass| remove_constant(klass) unless klass.to_s =~ /Router/ }
424
597
  end
@@ -451,7 +624,7 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
451
624
  Merb.logger.debug("Failed to remove constant #{object} from #{base}")
452
625
  end
453
626
  end
454
-
627
+
455
628
  private
456
629
 
457
630
  # "Better loading" of classes. If a class fails to load due to a NameError
@@ -489,10 +662,11 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
489
662
  if klasses.size == size_at_start && klasses.size != 0
490
663
  # Write all remaining failed classes and their exceptions to the log
491
664
  messages = error_map.only(*failed_classes).map do |klass, e|
492
- ["Could not load #{klass}:\n\n#{e.message} - (#{e.class})", "#{(e.backtrace || []).join("\n")}"]
665
+ ["Could not load #{klass}:\n\n#{e.message} - (#{e.class})",
666
+ "#{(e.backtrace || []).join("\n")}"]
493
667
  end
494
668
  messages.each { |msg, trace| Merb.logger.fatal!("#{msg}\n\n#{trace}") }
495
- raise LoadError, "#{messages[0][0]} (see log for details)"
669
+ Merb.fatal! "#{failed_classes.join(", ")} failed to load."
496
670
  end
497
671
  break if(klasses.size == size_at_start || klasses.size == 0)
498
672
  end
@@ -502,6 +676,31 @@ class Merb::BootLoader::LoadClasses < Merb::BootLoader
502
676
 
503
677
  end
504
678
 
679
+ class Merb::BootLoader::Router < Merb::BootLoader
680
+ class << self
681
+
682
+ def run
683
+ Merb::BootLoader::LoadClasses.load_file(router_file) if router_file
684
+ end
685
+
686
+ def reload!
687
+ if router_file
688
+ Merb::Router.reset!
689
+ Merb::BootLoader::LoadClasses.reload(router_file)
690
+ end
691
+ end
692
+
693
+ def router_file
694
+ @router_file ||= begin
695
+ if File.file?(router = Merb.dir_for(:router) / Merb.glob_for(:router))
696
+ router
697
+ end
698
+ end
699
+ end
700
+
701
+ end
702
+ end
703
+
505
704
  class Merb::BootLoader::Templates < Merb::BootLoader
506
705
  class << self
507
706
 
@@ -532,7 +731,9 @@ class Merb::BootLoader::Templates < Merb::BootLoader
532
731
  # template roots. eg app/views/shared/*
533
732
  template_paths << Dir["#{Merb.dir_for(:view)}/**/*.#{extension_glob}"] if Merb.dir_for(:view)
534
733
 
535
- template_paths.flatten.compact.uniq
734
+ # This ignores templates for partials, which need to be compiled at use time to generate
735
+ # a preamble that assigns local variables
736
+ template_paths.flatten.compact.uniq.grep(%r{^.*/[^_][^/]*$})
536
737
  end
537
738
  end
538
739
  end
@@ -562,13 +763,13 @@ class Merb::BootLoader::MimeTypes < Merb::BootLoader
562
763
  end
563
764
 
564
765
  class Merb::BootLoader::Cookies < Merb::BootLoader
565
-
766
+
566
767
  def self.run
567
768
  require 'merb-core/dispatch/cookies'
568
769
  Merb::Controller.send(:include, Merb::CookiesMixin)
569
770
  Merb::Request.send(:include, Merb::CookiesMixin::RequestMixin)
570
771
  end
571
-
772
+
572
773
  end
573
774
 
574
775
  class Merb::BootLoader::SetupSession < Merb::BootLoader
@@ -581,22 +782,22 @@ class Merb::BootLoader::SetupSession < Merb::BootLoader
581
782
  base_name = File.basename(file, ".rb")
582
783
  require file unless base_name == "container" || base_name == "store_container"
583
784
  end
584
-
785
+
585
786
  # Set some defaults.
586
787
  Merb::Config[:session_id_key] ||= "_session_id"
587
-
788
+
588
789
  # List of all session_stores from :session_stores and :session_store config options.
589
790
  config_stores = Merb::Config.session_stores
590
-
791
+
591
792
  # Register all configured session stores - any loaded session container class
592
793
  # (subclassed from Merb::SessionContainer) will be available for registration.
593
794
  Merb::SessionContainer.subclasses.each do |class_name|
594
- if(store = Object.full_const_get(class_name)) &&
795
+ if(store = Object.full_const_get(class_name)) &&
595
796
  config_stores.include?(store.session_store_type)
596
797
  Merb::Request.register_session_type(store.session_store_type, class_name)
597
798
  end
598
799
  end
599
-
800
+
600
801
  # Mixin the Merb::Session module to add app-level functionality to sessions
601
802
  Merb::SessionContainer.send(:include, Merb::Session)
602
803
  end
@@ -669,7 +870,7 @@ class Merb::BootLoader::RackUpApplication < Merb::BootLoader
669
870
  run Merb::Rack::Application.new
670
871
  }.to_app
671
872
  end
672
-
873
+
673
874
  end
674
875
  end
675
876
 
@@ -681,7 +882,7 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
681
882
  Thread.new do
682
883
  loop do
683
884
  sleep( seconds )
684
- block.call
885
+ yield
685
886
  end
686
887
  Thread.exit
687
888
  end
@@ -692,14 +893,6 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
692
893
  def self.run
693
894
  return unless Merb::Config[:reload_classes]
694
895
 
695
- TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do
696
- reload
697
- end
698
-
699
- end
700
-
701
- # Reloads all files.
702
- def self.reload
703
896
  paths = []
704
897
  Merb.load_paths.each do |path_name, file_info|
705
898
  path, glob = file_info
@@ -707,11 +900,26 @@ class Merb::BootLoader::ReloadClasses < Merb::BootLoader
707
900
  paths << Dir[path / glob]
708
901
  end
709
902
 
710
- paths << Merb.dir_for(:application) if Merb.dir_for(:application) && File.file?(Merb.dir_for(:application))
903
+ if Merb.dir_for(:application) && File.file?(Merb.dir_for(:application))
904
+ paths << Merb.dir_for(:application)
905
+ end
906
+
907
+ paths.flatten!
908
+
909
+ TimedExecutor.every(Merb::Config[:reload_time] || 0.5) do
910
+ GC.start
911
+ reload(paths)
912
+ end
913
+
914
+ end
915
+
916
+ # Reloads all files.
917
+ def self.reload(paths)
918
+ paths.each do |file|
919
+ next if LoadClasses::MTIMES[file] &&
920
+ LoadClasses::MTIMES[file] == File.mtime(file)
711
921
 
712
- paths.flatten.each do |file|
713
- next if Merb::BootLoader::LoadClasses::MTIMES[file] && Merb::BootLoader::LoadClasses::MTIMES[file] == File.mtime(file)
714
- Merb::BootLoader::LoadClasses.reload(file)
922
+ LoadClasses.reload(file)
715
923
  end
716
924
  end
717
925
  end