SleeplessByte/tempfile-fixture

View on GitHub
lib/tempfile/fixture.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'fileutils'
require 'tempfile'
require 'tempfile/fixture/version'

# Do a class eval to get around supercall mismatch across versions / implementations
# rubocop:disable Metrics/BlockLength
Tempfile.class_eval do

  ##
  # Fixture class for Tempfiles.
  #
  # @example Load a fixture file as a tempfile
  #
  #   Tempfile.Fixture('/path/to/data.txt').copy do |tempfile|
  #     # do something with the tempfile
  #   end
  #
  #   # the tempfile should be gone
  #
  # @example Don't unlink the tempfile
  #
  #   tempfile = Tempfile::Fixture.new('/path/to/data.txt').copy!
  #   tempfile # => the tempfile
  #
  class Fixture
    def initialize(path, tempfile_options: {})
      self.fixture = path
      self.tempfile_options = tempfile_options
    end

    def copy!
      file = Tempfile.new(tempfile_args, tempfile_options)
      FileUtils.copy_file(fixture, file.path, true)
      yield file if block_given?
      file
    end

    def copy(&block)
      file = copy!(&block)
      self
    ensure
      if file
        file.close unless file.closed?

        # Silently fail (hello windows)
        file.unlink rescue nil # rubocop:disable Style/RescueModifier
      end
    end

    private

    def tempfile_args
      name = File.basename(fixture)
      ext = File.extname(fixture)

      # Some files don't have an extension!
      return name unless ext && ext.length.positive?

      [name, ext.start_with?('.') ? ext : ".#{ext}"]
    end

    attr_accessor :fixture, :tempfile_options
  end

  # noinspection RubyConstantNamingConvention
  TempfileFixture = Fixture

  # noinspection RubyClassMethodNamingConvention
  def self.Fixture(path, binary: false, &block)
    raise ArgumentError, 'no block given' unless block_given?
    raise ArgumentError, 'no path given' unless path && path.length.positive?
    encoding = binary ? 'ascii-8bit' : 'utf-8'

    TempfileFixture.new(path, tempfile_options: { encoding: encoding })
                   .copy(&block)
  end
end
# rubocop:enable Metrics/BlockLength