Class: AutoReloader

Inherits:
Object
  • Object
show all
Extended by:
SingleForwardable
Includes:
Singleton
Defined in:
lib/auto_reloader.rb,
lib/auto_reloader/version.rb

Defined Under Namespace

Modules: RequireOverride

Constant Summary collapse

ActivatedMoreThanOnce =
Class.new RuntimeError
InvalidUsage =
Class.new RuntimeError
VERSION =
'0.2.0'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAutoReloader

Returns a new instance of AutoReloader.



28
29
30
# File 'lib/auto_reloader.rb', line 28

def initialize
  @activate_lock = Mutex.new
end

Instance Attribute Details

#default_delayObject (readonly)

Returns the value of attribute default_delay.



13
14
15
# File 'lib/auto_reloader.rb', line 13

def default_delay
  @default_delay
end

#default_onchangeObject (readonly)

Returns the value of attribute default_onchange.



13
14
15
# File 'lib/auto_reloader.rb', line 13

def default_onchange
  @default_onchange
end

#reloadable_pathsObject

Returns the value of attribute reloadable_paths.



13
14
15
# File 'lib/auto_reloader.rb', line 13

def reloadable_paths
  @reloadable_paths
end

Instance Method Details

#activate(reloadable_paths: [], onchange: true, delay: nil, watch_paths: nil, watch_latency: 1) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/auto_reloader.rb', line 33

def activate(reloadable_paths: [], onchange: true, delay: nil, watch_paths: nil,
            watch_latency: 1)
  @activate_lock.synchronize do
    raise ActivatedMoreThanOnce, "Can only activate Autoreloader once" if @reloadable_paths
    @default_delay = delay
    @default_onchange = onchange
    @watch_latency = watch_latency
    @require_lock = Monitor.new # monitor is like Mutex, but reentrant
    @reload_lock = Mutex.new
    @top_level_consts_stack = []
    @unload_constants = Set.new
    @unload_files = Set.new
    @last_reloaded = clock_time
    try_listen unless watch_paths == false
    self.reloadable_paths = reloadable_paths
    Object.include RequireOverride
  end
end

#reload!(delay: default_delay, onchange: default_onchange) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/auto_reloader.rb', line 90

def reload!(delay: default_delay, onchange: default_onchange)
  if onchange && !block_given?
    raise InvalidUsage, 'A block must be provided to reload! when onchange is true (the default)'
  end

  unload! unless reload_ignored = ignore_reload?(delay, onchange)

  result = nil
  if block_given?
    result = yield
    find_mtime
  end
  @last_reloaded = clock_time if delay
  result
end

#require(path, &block) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/auto_reloader.rb', line 57

def require(path, &block)
  was_required = false
  @require_lock.synchronize do
    @top_level_consts_stack << Set.new
    old_consts = Object.constants
    prev_consts = new_top_level_constants = nil
    begin
      was_required = yield
    ensure
      prev_consts = @top_level_consts_stack.pop
      if was_required
        new_top_level_constants = Object.constants - old_consts - prev_consts.to_a
        @top_level_consts_stack.each{|c| c.merge new_top_level_constants }
      end
    end
    return false unless was_required # was required already, do nothing
    full_loaded_path = $LOADED_FEATURES.last
    reloadable = reloadable?(full_loaded_path, path)
    if reloadable
      @reload_lock.synchronize do
        @unload_constants.merge new_top_level_constants
        @unload_files << full_loaded_path
      end
    end
  end
  was_required
end

#require_relative(path, fullpath) ⇒ Object



85
86
87
# File 'lib/auto_reloader.rb', line 85

def require_relative(path, fullpath)
  Object.require fullpath
end

#stop_listenerObject



115
116
117
# File 'lib/auto_reloader.rb', line 115

def stop_listener
  @listener.stop if @listener
end

#unload!Object



106
107
108
109
110
111
112
113
# File 'lib/auto_reloader.rb', line 106

def unload!
  @reload_lock.synchronize do
    @unload_files.each{|f| $LOADED_FEATURES.delete f }
    @unload_constants.each{|c| Object.send :remove_const, c }
    @unload_files = Set.new
    @unload_constants = Set.new
  end
end