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.3'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAutoReloader

Returns a new instance of AutoReloader.



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

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



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

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

#force_next_reloadObject



124
125
126
# File 'lib/auto_reloader.rb', line 124

def force_next_reload
  @force_reload = true
end

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



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/auto_reloader.rb', line 94

def reload!(delay: default_delay, onchange: default_onchange, watch_paths: @watch_paths)
  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, watch_paths)

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

#require(path, &block) ⇒ Object



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
84
85
86
87
# File 'lib/auto_reloader.rb', line 58

def require(path, &block)
  was_required = error = 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
    rescue Exception
      error = true
    ensure
      prev_consts = @top_level_consts_stack.pop
      return false if !error && !was_required # was required already, do nothing

      new_top_level_constants = Object.constants - old_consts - prev_consts.to_a

      (new_top_level_constants.each{|c| safe_remove_constant c }; raise) if error

      @top_level_consts_stack.each{|c| c.merge new_top_level_constants }

      full_loaded_path = $LOADED_FEATURES.last
      return was_required unless reloadable? full_loaded_path, path
      @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



89
90
91
# File 'lib/auto_reloader.rb', line 89

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

#stop_listenerObject



120
121
122
# File 'lib/auto_reloader.rb', line 120

def stop_listener
  @listener.stop if @listener
end

#unload!Object



110
111
112
113
114
115
116
117
118
# File 'lib/auto_reloader.rb', line 110

def unload!
  @force_reload = false
  @reload_lock.synchronize do
    @unload_files.each{|f| $LOADED_FEATURES.delete f }
    @unload_constants.each{|c| safe_remove_constant c }
    @unload_files = Set.new
    @unload_constants = Set.new
  end
end