Class: Stashify::Directory

Inherits:
Object
  • Object
show all
Defined in:
lib/stashify/directory.rb,
lib/stashify/directory/local.rb

Overview

A common abstraction for interacting with directories. All methods that need to interact with directories are assumed to adhere to the public methods defined here. Specifically, the methods #find, #write, #delete, and #files are guaranteed to exist and behave in a way that is consistent across all gems. Unless called out separately, documentation for those methods here will hold true of any implementations of this class.

Direct Known Subclasses

Local

Defined Under Namespace

Classes: Local

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name: nil, path: nil, files: []) ⇒ Directory

Basic information associated with a directory that is necessary to enable memory-based interactions.

Parameters:

  • name (String not containing a "/") (defaults to: nil)

    The name of the file. Either this or path must be defined.

  • path (String) (defaults to: nil)

    The path of the file, will populate name with everything following the final “/”.

  • files (defaults to: [])

    An array of Stashify::File and Stashify::Directory objects representing the contents of this directory.

Raises:

  • (StandardError)


42
43
44
45
46
47
48
# File 'lib/stashify/directory.rb', line 42

def initialize(name: nil, path: nil, files: [])
  raise StandardError, "name or path must be defined" unless name || path

  @path = path
  @name = name || ::File.basename(path)
  @files = files
end

Instance Attribute Details

#filesArray<Stashify::File and Stashify::Directory> (readonly)

Provides the files and subdirectories of this directory. In the base class, this is implemented as an attribute which defaults to an empty list, but most implementations will override this with a method. In most implementations, the performance cost of reading all of thie names in a directory to construct these objects is high enough that we only want to pay it if it’s actually needed.

Returns:



23
24
25
# File 'lib/stashify/directory.rb', line 23

def files
  @files
end

#nameObject (readonly)

The name of the directory. It is everything that follows the final “/” in the #path. This is always guaranteed to be populated.



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

def name
  @name
end

#pathObject (readonly)

The full path to the directory this represents. Anything after the final “/” will also be returned from #name. This is not necessarily guaranteed to be populated, but usually will be.



33
34
35
# File 'lib/stashify/directory.rb', line 33

def path
  @path
end

Instance Method Details

#==(other) ⇒ Object

Two directories are equal if their files are equal. This is distinct from being the same directory, which is served by the #eql? method.



152
153
154
# File 'lib/stashify/directory.rb', line 152

def ==(other)
  files == other.files
end

#delete(name) ⇒ Object

Delete provided name from the directory. If the item is a directory itself, then all of the contents will be copied.

For those looking to implement this method, it’s typically easier to implement #directory?, #delete_directory and #delete_file. The primary reason to override this method would be for performance reasons.

Parameters:

  • name (String)

    Name of the item to be deleted.



124
125
126
127
128
129
130
# File 'lib/stashify/directory.rb', line 124

def delete(name)
  if directory?(name)
    delete_directory(name)
  else
    delete_file(name)
  end
end

#delete_directory(name) ⇒ Object

Deletes the provided directory name. Typically you will want to interact with this functionality through #delete rather than directly, as it protects you from errors related to accidentally asking to delete a file as a directory.



136
137
138
139
# File 'lib/stashify/directory.rb', line 136

def delete_directory(name)
  subdir = directory(name)
  subdir.files.each { |file| subdir.delete(file.name) }
end

#delete_file(name) ⇒ Object

Deletes the provided file name. Typically you will want to interact with this functionality through #delete rather than directly, as it protects you from errors related to accidentally asking to delete a directory as a file.



145
146
147
# File 'lib/stashify/directory.rb', line 145

def delete_file(name)
  file(name).delete
end

#eql?(other) ⇒ Boolean

This answers if the two directories are the same, which is usually more specific than you want. If you wish to determine if all of the files are equal, consider #== instead..

Returns:

  • (Boolean)


159
160
161
# File 'lib/stashify/directory.rb', line 159

def eql?(other)
  self.class == other.class && name == other.name && path == other.path
end

#file(name) ⇒ Stashify::File

Return an object representing a single file in this directory.

Returns:

  • (Stashify::File)

    Return an object representing a single file in this directory.



165
166
167
# File 'lib/stashify/directory.rb', line 165

def file(name)
  Stashify::File.new(path: path_of(name))
end

#find(name) ⇒ Object

Look up the item in this directory represented by the provided name.

For those looking to implement this method, it’s typically more effective to override #directory?, #directory, #exists? and #file. Unless there are performance concerns with calling those, the default implementation will work pretty well.

Parameters:

  • name (String with no "/")

    The name of the desired item in this directory.

Returns:

  • Either a Stashify::File or Stashify::Directory object, depending on what that name represents.



63
64
65
66
67
68
69
# File 'lib/stashify/directory.rb', line 63

def find(name)
  if directory?(name)
    directory(name)
  elsif exists?(name)
    file(name)
  end
end

#path_of(*names) ⇒ Object

The full path to the item in this directory provided by the names. Any number of names can be provided, allowing arbitrarily deep paths to be constructed below this directory.



172
173
174
# File 'lib/stashify/directory.rb', line 172

def path_of(*names)
  ::File.join(path, *names)
end

#write(item) ⇒ Object

Write the provided item into the directory. If the item is a directory itself, then all of the contents will be copied.

For those looking to implement this method, it’s typically easier to implement #write_file and #write_directory. This helps you avoid having to know what type of object you’re dealing with.

Parameters:

  • item

    Either a Stashify::File or Stashify::Directory object. Note that these can be any implementation of these base classes, it’s not limited to the classes from the same provider.



83
84
85
86
87
88
89
# File 'lib/stashify/directory.rb', line 83

def write(item)
  if item.is_a?(Stashify::Directory)
    write_directory(item)
  else
    write_file(item)
  end
end

#write_directory(directory) ⇒ Object

Writes the provided directory. Typically you will want to interact with this functionality through #write rather than directly, as it protects you from errors related to accidentally passing a Stashify::File value in. It is primarily implemented separately to give a more specific hook for various implementations.

The default implementation might work for you, as it iterates through #files and writes them to the new subdirectory.



100
101
102
103
# File 'lib/stashify/directory.rb', line 100

def write_directory(directory)
  subdir = self.directory(directory.name)
  directory.files.each { |file| subdir.write(file) }
end

#write_file(file) ⇒ Object

Writes the provided file. Typically you will want to interact with this functionality through #write rather than directly, as it protects you from errors related to accidentally passing a Stashify::Directory value in. It is primarily implemented separately to give a more specific hook for various implementations.



111
112
113
# File 'lib/stashify/directory.rb', line 111

def write_file(file)
  file(file.name).write(file.contents)
end