Class: Merb::BootLoader::LoadClasses

Inherits:
Merb::BootLoader show all
Defined in:
lib/merb-core/bootloader.rb

Overview

Load all classes inside the load paths.

This is used in conjunction with Merb::BootLoader::ReloadClasses to track files that need to be reloaded, and which constants need to be removed in order to reload a file.

This also adds the model, controller, and lib directories to the load path, so they can be required in order to avoid load-order issues.

Constant Summary collapse

LOADED_CLASSES =
{}
MTIMES =
{}

Class Method Summary collapse

Methods inherited from Merb::BootLoader

after, after_app_loads, before, before_app_loads, default_framework, finished?, inherited, move_klass

Class Method Details

.load_classes(*paths) ⇒ Object

Load classes from given paths - using path/glob pattern.

*paths<Array>

Array of paths to load classes from - may contain glob pattern



371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/merb-core/bootloader.rb', line 371

def load_classes(*paths)
  orphaned_classes = []
  paths.flatten.each do |path|
    Dir[path].each do |file|
      begin
        load_file file
      rescue NameError => ne
        orphaned_classes.unshift(file)
      end
    end
  end
  load_classes_with_requirements(orphaned_classes)
end

.load_file(file) ⇒ Object

Parameters

file<String>

The file to load.



360
361
362
363
364
365
# File 'lib/merb-core/bootloader.rb', line 360

def load_file(file)
  klasses = ObjectSpace.classes.dup
  load file
  LOADED_CLASSES[file] = ObjectSpace.classes - klasses
  MTIMES[file] = File.mtime(file)
end

.reload(file) ⇒ Object

Parameters

file<String>

The file to reload.



387
388
389
# File 'lib/merb-core/bootloader.rb', line 387

def reload(file)
  remove_classes_in_file(file) { |f| load_file(f) }
end

.reload_router!Object

Reload the router to regenerate all routes.



392
393
394
395
396
397
# File 'lib/merb-core/bootloader.rb', line 392

def reload_router!
  if File.file?(router_file = Merb.dir_for(:router) / Merb.glob_for(:router))
    Merb::Router.reset!
    reload router_file
  end
end

.remove_classes_in_file(file) {|file| ... } ⇒ Object

Parameters

file<String>

The file to remove classes for.

&block

A block to call with the file that has been removed.

Yields:

  • (file)


402
403
404
405
406
407
408
409
# File 'lib/merb-core/bootloader.rb', line 402

def remove_classes_in_file(file, &block)
  Merb.klass_hashes.each {|x| x.protect_keys!}
  if klasses = LOADED_CLASSES.delete(file)
    klasses.each { |klass| remove_constant(klass) unless klass.to_s =~ /Router/ }
  end
  yield file if block_given?
  Merb.klass_hashes.each {|x| x.unprotect_keys!}
end

.remove_constant(const) ⇒ Object

Parameters

const<Class>

The class to remove.



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/merb-core/bootloader.rb', line 413

def remove_constant(const)
  # This is to support superclasses (like AbstractController) that track
  # their subclasses in a class variable. Classes that wish to use this
  # functionality are required to alias it to _subclasses_list. Plugins
  # for ORMs and other libraries should keep this in mind.
  superklass = const
  until (superklass = superklass.superclass).nil?
    if superklass.respond_to?(:_subclasses_list)
      superklass.send(:_subclasses_list).delete(klass)
      superklass.send(:_subclasses_list).delete(klass.to_s)
    end
  end

  parts = const.to_s.split("::")
  base = parts.size == 1 ? Object : Object.full_const_get(parts[0..-2].join("::"))
  object = parts[-1].to_s
  begin
    base.send(:remove_const, object)
    Merb.logger.debug("Removed constant #{object} from #{base}")
  rescue NameError
    Merb.logger.debug("Failed to remove constant #{object} from #{base}")
  end
end

.runObject

Load all classes from Merb’s native load paths.



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/merb-core/bootloader.rb', line 339

def run
  # Add models, controllers, helpers and lib to the load path
  $LOAD_PATH.unshift Merb.dir_for(:model)
  $LOAD_PATH.unshift Merb.dir_for(:controller)
  $LOAD_PATH.unshift Merb.dir_for(:lib)
  $LOAD_PATH.unshift Merb.dir_for(:helper)

  # Load application file if it exists - for flat applications
  load_file Merb.dir_for(:application) if File.file?(Merb.dir_for(:application))
  
  # Load classes and their requirements
  Merb.load_paths.each do |component, path|
    next unless path.last && component != :application
    load_classes(path.first / path.last)
  end

  Merb::Controller.send :include, Merb::GlobalHelpers
end