Class: Impromptu::File

Inherits:
Object
  • Object
show all
Defined in:
lib/impromptu/file.rb

Constant Summary collapse

RELOADABLE_EXTENSIONS =
%w{rb}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, folder, preload = false, provides = []) ⇒ File

Returns a new instance of File.



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/impromptu/file.rb', line 6

def initialize(path, folder, preload=false, provides=[])
  @path               = path
  @folder             = folder
  @resources          = OrderedSet.new
  @related_resources  = Set.new
  @related_files      = Set.new
  @frozen             = false
  @modified_time      = nil
  @dirty              = true
  @preload            = preload
  @provides           = [provides].compact.flatten
end

Instance Attribute Details

#folderObject (readonly)

Returns the value of attribute folder.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def folder
  @folder
end

#modified_timeObject (readonly)

Returns the value of attribute modified_time.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def modified_time
  @modified_time
end

#pathObject (readonly)

Returns the value of attribute path.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def path
  @path
end

#preloadObject

Returns the value of attribute preload.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def preload
  @preload
end

Returns the value of attribute related_files.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def related_files
  @related_files
end

Returns the value of attribute related_resources.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def related_resources
  @related_resources
end

#resourcesObject (readonly)

Returns the value of attribute resources.



3
4
5
# File 'lib/impromptu/file.rb', line 3

def resources
  @resources
end

Instance Method Details

Add a file to the list of files related to this file.



155
156
157
158
# File 'lib/impromptu/file.rb', line 155

def add_related_file(file)
  @related_files << file
  @dirty = true
end

#add_resource_definitionObject

Should only be called once, and only after a file has been loaded for the first time. If the file was defined with a list of resources the file implements, inform each resource that this file implements the resource. Otherwise the name of the file is used to determine the resource provided (e.g klass_one.rb would be assumed to provide KlassOne).



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/impromptu/file.rb', line 186

def add_resource_definition
  # unless defined, we assume the name of the file implies
  # the resource that is provided by the file
  if @provides.empty?
    @provides << module_symbol_from_path
  end
  
  # add a reference of this file to every appropriate resource
  @provides.each do |resource_name|
    resource = Impromptu.root_resource.get_or_create_child(combine_symbol_with_namespace(resource_name))
    resource.add_file(self)
    resource.preload = preload?
    @resources << resource
  end
end

#eql?(other) ⇒ Boolean

Override eql? so two files with the same path will be considered equal by ordered set.

Returns:

  • (Boolean)


21
22
23
# File 'lib/impromptu/file.rb', line 21

def eql?(other)
  other.path == @path
end

#freezeObject

Traverse the file/resource graph to determine which total set of files and resources are related to this file. For instance, if a resource provided by this file is also defined in another, both files, and the total set of resources provided by these files, are included. If further resources are provided, those resources along with any other files defining them, are also included.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/impromptu/file.rb', line 50

def freeze
  return if @frozen
  remaining_resources = @resources.to_a
  remaining_files = [self]
  
  while remaining_resources.size > 0 || remaining_files.size > 0
    if resource = remaining_resources.shift
      @related_resources << resource
      resource.files.each do |file|
        remaining_files << file unless @related_files.include?(file)
      end
    end
    
    if file = remaining_files.shift
      @related_files << file
      file.add_related_file(self)
      file.resources.each do |resource|
        remaining_resources << resource unless @related_resources.include?(resource)
      end
    end
  end
  
  @frozen = true
end

#hashObject

Override hash so two files with the same path will result in the same hash value.



27
28
29
# File 'lib/impromptu/file.rb', line 27

def hash
  @path.hash
end

#loadObject

Load the file is possible, after loading any external dependencies for the component owning this file. The modified time is updated so we know if a change is made to the file at a later date. This does a simple load of the file and doesn’t unload any resources beforehand. You typically want to use reload to ensure that the resources provided by this file are fully unloaded and reloaded in one go.



109
110
111
112
113
114
# File 'lib/impromptu/file.rb', line 109

def load
  @folder.component.load_external_dependencies
  Kernel.load @path if reloadable?
  @modified_time = @path.mtime
  @dirty = false
end

#loaded?Boolean

Indicates if this file is currently loaded

Returns:

  • (Boolean)


141
142
143
# File 'lib/impromptu/file.rb', line 141

def loaded?
  !@modified_time.nil?
end

#modified?Boolean

Returns true if the current modification time of the underlying file is greater than the modified_time of the file when we last loaded it.

Returns:

  • (Boolean)


130
131
132
# File 'lib/impromptu/file.rb', line 130

def modified?
  resources_loaded? && (@dirty || @modified_time.nil? || (@path.mtime > @modified_time))
end

#preload?Boolean

True if this file needs to be preloaded before other files are automatically loaded on demand

Returns:

  • (Boolean)


39
40
41
# File 'lib/impromptu/file.rb', line 39

def preload?
  @preload
end

#refreezeObject

Unfreeze and freeze a files association lists



84
85
86
87
# File 'lib/impromptu/file.rb', line 84

def refreeze
  unfreeze
  freeze
end

#reloadObject

Load (or reload) all of the resources provided by this file. If a resource is provided by multiple files, those files will also be reloaded (and the resources provided in those files reloaded). For this reason it’s advisable to declare a single resource per file, otherwise the dependencies between files and resources can cause large subsections of the component graph to be reloaded together.



96
97
98
99
# File 'lib/impromptu/file.rb', line 96

def reload
  @related_resources.each {|resource| resource.unload}
  @related_files.each {|file| file.load}
end

#reload_if_modifiedObject

Reloads the associated resources only if the underlying file has been modified since the last time it was loaded.



136
137
138
# File 'lib/impromptu/file.rb', line 136

def reload_if_modified
  reload if modified?
end

#reloadable?Boolean

True if the file has never been loaded before, or if the file is of a type that can be reloaded (i.e ruby source as opposed to C extensions).

Returns:

  • (Boolean)


205
206
207
208
# File 'lib/impromptu/file.rb', line 205

def reloadable?
  return true if !loaded?
  RELOADABLE_EXTENSIONS.include?(@path.extname[1..-1])
end

#removeObject

Delete references to this file from any resources or other files. This does not unload the resource, so if loaded, the resource will be defined by a file which is no longer tracked.



169
170
171
172
173
174
175
176
177
178
# File 'lib/impromptu/file.rb', line 169

def remove
  @related_files.each {|file| file.remove_related_file(self)}
  @resources.each do |resource|
    if resource.files.size == 1
      resource.remove
    else
      resource.remove_file(self)
    end
  end
end

Remove a file from the list of files related to this file.



161
162
163
164
# File 'lib/impromptu/file.rb', line 161

def remove_related_file(file)
  @related_files.delete(file)
  @dirty = true
end

#resources_loaded?Boolean

True if any of the resources provided by this file have been loaded.

Returns:

  • (Boolean)


147
148
149
150
151
152
# File 'lib/impromptu/file.rb', line 147

def resources_loaded?
  @resources.each do |resource|
    return true if resource.loaded?
  end
  false
end

#unfreezeObject

Unfreeze this file by clearing the related files and resources lists.



77
78
79
80
81
# File 'lib/impromptu/file.rb', line 77

def unfreeze
  @related_resources = Set.new
  @related_files = Set.new
  @frozen = false
end

#unloadObject

Unload all of the resources provided by this file. This doesn’t just unload the parts of a resource defined by this file, but the entire resource itself. i.e if there are two files defining a resource, unloading one file will unload the resource completely.



121
122
123
124
125
# File 'lib/impromptu/file.rb', line 121

def unload
  resources.each {|resource| resource.unload}
  @modified_time = nil
  @dirty = true
end