lib/stashify/file.rb in stashify-3.2.0 vs lib/stashify/file.rb in stashify-3.2.1

- old
+ new

@@ -1,33 +1,94 @@ # frozen_string_literal: true require "stashify" module Stashify + # A common abstraction for interacting with files. All methods that + # need to interact with files are assumed to adhere to the methods + # defined here. Specifically the methods {#write}, {#delete}, + # {#contents} and {#exists?} 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. class File - attr_reader :name, :path, :contents + # Provides the contents of this file. In the base class, this is + # implemented as an attribute, but most implementations will + # override this with a method. In most implementations, the + # performance cost of reading the file is high enough that we only + # want to pay it if it's actually needed. + attr_reader :contents - def initialize(name: nil, path: nil, contents: "") + # The name of the file is the actual filename in a directory. In + # other words, it is everything that follows the final "/" in the + # {#path}. This is always guaranteed to be populated. + attr_reader :name + + # The full path to the file this represents. Anything after the + # final "/" will also be returned from {#name}. This is not + # necessarily guaranteed to be populated, but usually will be. + attr_reader :path + + # Basic information associated with a file that is necessary to + # enable memory-based interactions. + # + # @param name [String not containing a "/"] The name of the file. Either this or path must be defined. + # @param path [String] The path of the file, will populate name with everything following the final "/". + # @param contents [String] The contents of the file, if nil this object will mimic a missing file. + def initialize(name: nil, path: nil, contents: nil) raise StandardError, "name or path must be defined" unless name || path raise Stashify::InvalidFile, "Name '#{name}' contains a /" if name && name =~ %r{/} @path = path @name = name || ::File.basename(path) @contents = contents end + # Persists the provided contents into {#path}. If that file does + # not exist, it creates it in the process. Otherwise it updates + # the existing file. + # + # In general, if {#exists?} returns false before this is called it + # will return true after this is called. + # + # @note For the base implementation, it will assign something to + # @contents. The value of this instance variable should not be + # relied upon outside of the base implementation though, every + # other implementation so far overrides to an action more + # appropriate to its storage medium. + # + # @param contents [String] A String describing the contents of the file. + # @return No guarantees are made as to the return value of this method, + # it will largely depend on the implementation of the implementing class. def write(contents) @contents = contents end + # Deletes the underlying file. + # + # In general, if {#exists?} returns true prior to this method + # being called, it will no longer return true after this method is + # called. + # + # @return No guarantees are made as to the return value of this method, + # it will largely depend on the implementation of the implementing class. def delete @contents = nil end + # Answers if the file exists. In general, it will always return + # true after {#write} is called and always return false after + # {#delete} is called. + # + # @note The base class checks if {#contents} returns nil, but this + # is extremely unlikely for other implementations. def exists? !contents.nil? end + # Two files are considered equal if they have the same name and + # contents. This means that equality holds between files in two + # separate directories. def ==(other) name == other.name && contents == other.contents end end end