Module: Grape::Reload::Watcher

Defined in:
lib/grape/reload/watcher.rb

Constant Summary collapse

MTIMES =
{}

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.sourcesObject (readonly)

Returns the value of attribute sources.



11
12
13
# File 'lib/grape/reload/watcher.rb', line 11

def sources
  @sources
end

Class Method Details

.clearObject



71
72
73
74
# File 'lib/grape/reload/watcher.rb', line 71

def clear
  MTIMES.each_key{|f| Storage.remove(f)}
  MTIMES.clear
end

.constant_excluded?(const) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/grape/reload/watcher.rb', line 49

def constant_excluded?(const)
  @sources.class_file(const).nil?
end

.feature_excluded?(file) ⇒ Boolean

Tells if a feature should be excluded from Reloader tracking.

Returns:

  • (Boolean)


45
46
47
# File 'lib/grape/reload/watcher.rb', line 45

def feature_excluded?(file)
  @sources.file_excluded?(file)
end

.file_changed?(file) ⇒ Boolean

Returns true if the file is new or it’s modification time changed.

Returns:

  • (Boolean)


125
126
127
# File 'lib/grape/reload/watcher.rb', line 125

def file_changed?(file)
  file_new?(file) || File.mtime(file) > MTIMES[file]
end

.file_new?(file) ⇒ Boolean

Returns:

  • (Boolean)


129
130
131
# File 'lib/grape/reload/watcher.rb', line 129

def file_new?(file)
  MTIMES[file].nil?
end

.files_for_rotationObject



53
54
55
56
# File 'lib/grape/reload/watcher.rb', line 53

def files_for_rotation
  files = Set.new
  files += @sources.sorted_files.map{|p| Dir[p]}.flatten.uniq
end

.load_files!Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/grape/reload/watcher.rb', line 76

def load_files!
  files_to_load = files_for_rotation.to_a
  tries = {}
  while files_to_load.any?
    f = files_to_load.shift
    tries[f] = 1 unless tries[f]
    begin
      safe_load(f, cyclic: true, force: true)
    rescue
      logger.error $!
      tries[f] += 1
      if tries[f] < 3
        files_to_load << f
      else
        raise
      end
    end
  end
end

.loggerObject



14
# File 'lib/grape/reload/watcher.rb', line 14

def logger; Grape::RackBuilder.logger end

.rack_builderObject



12
# File 'lib/grape/reload/watcher.rb', line 12

def rack_builder; Grape::RackBuilder end

.reload!Object



96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/grape/reload/watcher.rb', line 96

def reload!
  files = @sources.fs_changes{|file|
    File.mtime(file) > MTIMES[file]
  }
  changed_files_sorted = @sources.sorted_files.select{|f| files[:changed].include?(f)}
  @sources.files_reloading do
    changed_files_sorted.each{|f| safe_load(f)}
  end
  changed_files_sorted.map{|f| @sources.dependent_classes(f) }.flatten.uniq.each {|class_name|
    next unless (klass = class_name.constantize).kind_of? Class
    klass.reinit! if klass.respond_to?('reinit!')
  }
end

.remove_constant(const) ⇒ Object

Removes the specified class and constant.



113
114
115
116
117
118
119
120
# File 'lib/grape/reload/watcher.rb', line 113

def remove_constant(const)
  return if constant_excluded?(const)
  base, _, object = const.to_s.rpartition('::')
  base = base.empty? ? Object : base.constantize
  base.send :remove_const, object
  logger.devel "Removed constant #{const} from #{base}"
rescue NameError
end

.remove_feature(file) ⇒ Object

Tells if a feature should be excluded from Reloader tracking.



38
39
40
# File 'lib/grape/reload/watcher.rb', line 38

def remove_feature(file)
  $LOADED_FEATURES.delete(file) unless feature_excluded?(file)
end

.safe_load(file, options = {}) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/grape/reload/watcher.rb', line 16

def safe_load(file, options={})
  return unless options[:force] || file_changed?(file)

  Storage.prepare(file) # might call #safe_load recursively
  logger.debug((file_new?(file) ? "loading" : "reloading") + " #{file}" )
  begin
    with_silence{ require(file) }
    Storage.commit(file)
    update_modification_time(file)
  rescue Exception => exception
    unless options[:cyclic]
      logger.exception exception, :short
      logger.error "Failed to load #{file}; removing partially defined constants"
    end
    Storage.rollback(file)
    raise
  end
end

.setup(options) ⇒ Object



58
59
60
61
# File 'lib/grape/reload/watcher.rb', line 58

def setup(options)
  @sources = options[:sources]
  load_files!
end

.update_modification_time(file) ⇒ Object

Macro for mtime update.



66
67
68
# File 'lib/grape/reload/watcher.rb', line 66

def update_modification_time(file)
  MTIMES[file] = File.mtime(file)
end