Class: Ramaze::SourceReload

Inherits:
Object show all
Defined in:
lib/ramaze/sourcereload.rb

Overview

SourceReload provides a way to reload changed files automatically during runtime. Its default behaviour in Ramaze is to check periodically for files with newer mtime and then attempts to load them in a controlled manner.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(interval = 1) ⇒ SourceReload

Take interval for files that are going to be reloaded.



19
20
21
22
23
# File 'lib/ramaze/sourcereload.rb', line 19

def initialize(interval = 1)
  @interval = interval
  @map, @files, @paths = [], [], []
  @mtimes = {}
end

Instance Attribute Details

#intervalObject

Returns the value of attribute interval.



12
13
14
# File 'lib/ramaze/sourcereload.rb', line 12

def interval
  @interval
end

#mapObject

Returns the value of attribute map.



12
13
14
# File 'lib/ramaze/sourcereload.rb', line 12

def map
  @map
end

#threadObject

Returns the value of attribute thread.



12
13
14
# File 'lib/ramaze/sourcereload.rb', line 12

def thread
  @thread
end

Class Method Details

.startup(options = {}) ⇒ Object

Takes value of Global.sourcereload and unless it’s false calls #start



34
35
36
37
38
39
40
# File 'lib/ramaze/sourcereload.rb', line 34

def self.startup(options = {})
  interval = Global.sourcereload
  instance = new(interval)
  Thread.main[:sourcereload] = instance
  instance.reload # initial scan of all files
  instance.start if interval
end

Instance Method Details

#all_reload_filesObject

Scans loaded features and paths for file-paths, filters them in the end according to the trait



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ramaze/sourcereload.rb', line 82

def all_reload_files
  files = Array[$0, *$LOADED_FEATURES]
  paths = Array['./', *$LOAD_PATH]

  unless [@files, @paths] == [files, paths]
    @files, @paths = files.dup, paths.dup

    @map = files.map{|file|
      if Pathname.new(file).absolute?
        file
      else
        path = paths.find{|pa|
          ex = File.expand_path(File.join(pa, file))
          File.exists?(ex)
        }
        File.expand_path(File.join(path, file)) if path
      end
    }.compact
  end

  @map.grep(class_trait[:reload_glob])
end

#mtime(file) ⇒ Object

Safe mtime



107
108
109
110
111
# File 'lib/ramaze/sourcereload.rb', line 107

def mtime(file)
  File.mtime(file)
rescue Errno::ENOENT
  false
end

#reloadObject

One iteration of reload will look for files that changed since the last iteration and will try to #safe_load it. This method is quite handy if you want direct control over when your code is reloaded

Usage example:

trap :HUP do
  Ramaze::Log.info "reloading source"
  Thread.main[:sourcereload].reload
end


66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/ramaze/sourcereload.rb', line 66

def reload
  SourceReloadHooks.before_reload
  all_reload_files.each do |file|
    mtime = mtime(file)

    next if (@mtimes[file] ||= mtime) == mtime

    Log.debug("reload #{file}")
    @mtimes[file] = mtime if safe_load(file)
  end
  SourceReloadHooks.after_reload
end

#reloaderObject

Start reload loop in separate Thread



44
45
46
47
48
49
50
51
# File 'lib/ramaze/sourcereload.rb', line 44

def reloader
  Thread.new do
    loop do
      reload
      sleep(@interval)
    end
  end
end

#safe_load(file) ⇒ Object

A safe Kernel::load, issuing the SourceReloadHooks depending on the result.



116
117
118
119
120
121
122
123
124
# File 'lib/ramaze/sourcereload.rb', line 116

def safe_load(file)
  SourceReloadHooks.before_safe_load(file)
  load(file)
  SourceReloadHooks.after_safe_load_succeed(file)
  true
rescue Object => ex
  SourceReloadHooks.after_safe_load_failed(file, ex)
  false
end

#startObject

start reloader-thread and assign it to this instance.



27
28
29
30
# File 'lib/ramaze/sourcereload.rb', line 27

def start
  Log.dev("initialize automatic source reload every #{interval} seconds")
  @thread = reloader
end