class FileName

The class to create filename that is not duplicated. We select type of additional part of filename: number or time.

Constants

OPTIONS_CREATE
VERSION

Attributes

configuration_key[RW]
format[RW]

Public Class Methods

configuration(*args) click to toggle source
# File lib/filename.rb, line 341
def self.configuration(*args)
  self.manage.configuration(*args)
end
create(basepath, *rest) click to toggle source

Executing FileName.new and FileName.create, we get new filename. The same options of FileName.new are available.

# File lib/filename.rb, line 330
def self.create(basepath, *rest)
  self.new(basepath, *rest).create
end
load(str) click to toggle source
# File lib/filename.rb, line 315
def self.load(str)
  filename = Marshal.load(str)
  if key = filename.configuration_key
    opts = self.manage.configuration_setting(key)
    filename.format = opts[:format]
  end
  filename
end
load_from(path) click to toggle source
# File lib/filename.rb, line 324
def self.load_from(path)
  self.load(File.read(path))
end
manage() click to toggle source
# File lib/filename.rb, line 336
def self.manage
  @@manage = FileName::Manage.new unless @@manage
  @@manage
end
new(basepath, *rest) click to toggle source

The options are following:

:start (Fixnum)

If ID string type is number, the ID starts from the specified number.

:digit (Fixnum)

When we create additional part of a filename, we use a string of ID number with specified digit.

:delimiter (String)

We use specified string for delimiter between base name and additional part. Default is ‘.’ if position is suffix. Otherwise, ‘_’.

:type (:number or :time)

We specify type of additional part: :number or :time. Default is :number.

:format (String or Proc)

We specify format string of additional part or proc object to create additional part. If type is :time, the format string is used by Time#strftime. For :number type, the string is a farst argument of sprintf(format, number). Proc object takes an object of Time or Integer for respective types.

:position (:prefix, :suffix, or :middle)

We specify of position of additional part of filename.

:path

We sepecify if path created by FileName#create is absolute or relative. Default is absolute.

:data

We specify hash expressing instance variables for evaluation of format proc, which is set by an option :format. If we set { :a => 1, :b => 2 } for :data option, we can use @a and @b in proc object set by :format option.

:filter

We specify filters :before and :after for basename without suffix, which is got by File.basename(path, “.*”)

:extension

Default value of the option of FileName#create.

:add

Default value of the option of FileName#create.

:directory

Default value of the option of FileName#create.

:file

Default value of the option of FileName#create.

# File lib/filename.rb, line 65
def initialize(basepath, *rest)
  if Hash === rest[-1]
    opts = rest.delete_at(-1)
  else
    opts = {}
  end
  path = File.join(basepath, *rest)
  @relative_path_p = (opts[:path] == :relative)
  if @relative_path_p
    @basepath = path
  else
    @basepath = File.expand_path(path)
  end
  @number = opts[:start] || 0
  @digit = opts[:digit] || 2
  if @digit < 1
    raise ArgumentError, "Number of digit must be positive."
  end
  @type = opts[:type] || :number
  @position = opts[:position] || :suffix
  @delimiter = opts[:delimiter] || (@position == :suffix ? '.' : '_')
  @format = opts[:format]
  @last_addition = nil
  @default_create = {}
  opts.each do |key, val|
    if OPTIONS_CREATE.include?(key)
      @default_create[key] = val
    end
  end
  @configuration_key = nil
  @data = Object.new
  if opts[:data]
    opts[:data].each do |key, val|
      @data.instance_variable_set("@#{key}", val)
    end
  end
  @filter = opts[:filter] || {}
end

Public Instance Methods

create(opts = {}) click to toggle source

The options are following:

:extension (String of extension)

If we want to change extension, we set the value of the option. Note that if we specify “txt” as :extension option, generated filesame is the format “SOME_STRING.txt”; that is, this method adds “.” + (specified extension).

:add (:always, :auto, or :prohibit)

We specify if the additional part is used.

  • :always - We always add.

  • :auto - If the file exists, we add.

  • :prohibit - Even if the file exists, we do not add.

:directory (:self, :parent, or nil)

If the value is :self, we make directory of created filename. If the value is :parent, we make parent directory of created filename. If the value is nil, we do nothing.

:file

If the value is :overwrite, we create a new empty file. If the value is :write and the file does not exist, we create an empty file. If the value is nil, we do nothing.

# File lib/filename.rb, line 264
def create(opts = {})
  basepath = @basepath
  if @filter[:before]
    basepath = filter_exec(@filter[:before], basepath)
  end
  base = get_basepath(basepath, get_option_create(opts, :extension))
  opt_add = get_option_create(opts, :add)
  if addition = get_addition(opt_add, base)
    path = add_addition(base, addition)
    while File.exist?(path)
      if addition = get_addition(opt_add, base)
        path = add_addition(base, addition)
      else
        raise "Can not create new filename."
      end
    end
    path
  else
    path = base
  end
  if @filter[:after]
    path = filter_exec(@filter[:after], path)
  end
  create_directory(path, get_option_create(opts, :directory))
  write_file(path, get_option_create(opts, :file))
  path
end
dump() click to toggle source

If @format is a Proc object, we can not dump a FileName object. But, even if @format is Proc object, the object created from configuration can be dumped.

# File lib/filename.rb, line 295
def dump
  if not Proc === @format
    dumped = Marshal.dump(self)
  elsif @configuration_key
    tmp = @format
    @format = nil
    dumped = Marshal.dump(self)
    @format = tmp
  else
    raise "Can not dump."
  end
  dumped
end
relative_path?() click to toggle source
# File lib/filename.rb, line 119
def relative_path?
  @relative_path_p
end
save_to(path) click to toggle source
# File lib/filename.rb, line 309
def save_to(path)
  open(path, 'w') do |f|
    f.print dump
  end
end

Private Instance Methods

add_addition(filename, addition) click to toggle source
# File lib/filename.rb, line 170
def add_addition(filename, addition)
  case @position
  when :prefix
    dir, base = File.split(filename)
    dir + '/' + addition + @delimiter + base
  when :middle
    dir, base = File.split(filename)
    ext = File.extname(base)
    if ext.size > 0
      filename.sub(Regexp.new("\\#{ext}$"), @delimiter + addition + ext)
    else
      filename + @delimiter + addition
    end
  else # :suffix
    filename + @delimiter + addition
  end
end
create_directory(base, dir_opt) click to toggle source
# File lib/filename.rb, line 194
def create_directory(base, dir_opt)
  if dir_opt
    case dir_opt
    when :self
      dir = base
    when :parent
      dir = File.dirname(base)
    else
      raise ArgumentError, "Invalid directory option."
    end
    FileUtils.mkdir_p(dir)
  end
end
create_number_addition(number) click to toggle source
# File lib/filename.rb, line 135
def create_number_addition(number)
  case @format
  when String
    sprintf(@format, number)
  when Proc
    @data.instance_exec(number, &@format)
  else
    sprintf("%0#{@digit}d", number)  
  end
end
create_time_addition(t) click to toggle source
# File lib/filename.rb, line 123
def create_time_addition(t)
  case @format
  when String
    t.strftime(@format)
  when Proc
    @data.instance_exec(t, &@format)
  else
    t.strftime("%Y%m%d_%H%M%S_") + sprintf("%06d", t.usec)
  end
end
filter_exec(filter, path) click to toggle source
# File lib/filename.rb, line 231
def filter_exec(filter, path)
  dir, basename = File.split(path)
  extname = File.extname(basename)
  basename_new = filter.call(basename.sub(/#{extname}$/, "")) + extname
  if relative_path? && dir == "."
    basename_new
  else
    File.join(dir, basename_new)
  end
end
get_addition(add, filename) click to toggle source
# File lib/filename.rb, line 147
def get_addition(add, filename)
  if add != :prohibit && (add == :always || File.exist?(filename))
    case @type
    when :time
      s = create_time_addition(Time.now)
    when :number
      s = create_number_addition(@number)
      @number += 1
    else
      raise "Invalid type of addition."
    end
    if s.size == 0 || s.include?(' ') || s.include?('/')
      raise "Invalid additional part of filename: #{s.inspect}"
    elsif @last_addition == s
      raise "Create same addition: #{s.inspect}"
    end
    @last_addition = s
    return s
  end
  nil
end
get_basepath(basepath, extension = nil) click to toggle source
# File lib/filename.rb, line 104
def get_basepath(basepath, extension = nil)
  if extension
    extension = '.' + extension unless extension[0] == '.'
    oldext = File.extname(basepath)
    if oldext.size > 0
      basepath.sub(Regexp.new("\\#{oldext}$"), extension)
    else
      basepath + extension
    end
  else
    basepath
  end
end
get_option_create(opts, key) click to toggle source
# File lib/filename.rb, line 189
def get_option_create(opts, key)
  opts.has_key?(key) ? opts[key] : @default_create[key]
end
touch_file(path) click to toggle source
# File lib/filename.rb, line 209
def touch_file(path)
  FileUtils.mkdir_p(File.dirname(path))
  open(path, 'w') {}
end
write_file(path, file_opt) click to toggle source
# File lib/filename.rb, line 215
def write_file(path, file_opt)
  if file_opt
    case file_opt
    when :write
      unless File.exist?(path)
        touch_file(path)
      end
    when :overwrite
      touch_file(path)
    else
      raise ArgumentError, "Invalid file option."
    end
  end
end