module DumbDelimited::ClassMethods

Public Instance Methods

append(path, models) click to toggle source

Appends a collection of model objects to a file in delimited format. Convenience shortcut for {write} with +append: true+.

@param path [String, Pathname] @param models [Enumerable<Struct>] @return [void]

# File lib/dumb_delimited.rb, line 295
def append(path, models)
  write(path, models, append: true)
end
delimiter() click to toggle source

Returns the column delimiter used in IO operations. Defaults to a comma (",").

Equivalent to options[:col_sep].

@return [String]

# File lib/dumb_delimited.rb, line 140
def delimiter
  self.options[:col_sep]
end
delimiter=(delim) click to toggle source

Sets the column delimiter used in IO operations. The new value will be used in all future IO operations for the model class. Any delimiter can be safely chosen, and all IO operations will quote field values as necessary.

Equivalent to options[:col_sep] = delim.

@example

Point = DumbDelimited[:x, :y, :z]
p = Point.new(1, 2, 3)
p.to_s  # == "1,2,3"
Point.delimiter = "|"
p.to_s  # == "1|2|3"

@param delim [String] @return [String]

# File lib/dumb_delimited.rb, line 160
def delimiter=(delim)
  self.options[:col_sep] = delim
end
options() click to toggle source

Returns the CSV options Hash. The Hash is not +dup+ed and can be modified directly. Any modifications will be applied to all future IO operations for the model class.

For detailed information about available options, see Ruby's {docs.ruby-lang.org/en/trunk/CSV.html#method-c-new CSV class}.

@return [Hash<Symbol, Object>]

# File lib/dumb_delimited.rb, line 109
def options
  @options ||= if superclass == Struct
    CSV::DEFAULT_OPTIONS.merge(
      skip_blanks: true,
      liberal_parsing: true,
    )
  else
    superclass.options.dup
  end
end
options=(opts) click to toggle source

Sets the CSV options Hash. The entire Hash is replaced, and the new values will be applied to all future IO operations for the model class. To set options individually, see {options}.

For detailed information about available options, see Ruby's {docs.ruby-lang.org/en/trunk/CSV.html#method-c-new CSV class}.

@param opts [Hash<Symbol, Object>] @return [Hash<Symbol, Object>]

# File lib/dumb_delimited.rb, line 130
def options=(opts)
  @options = opts
end
parse(data) click to toggle source

Parses a string or IO object into an array of model objects.

@example

Point = DumbDelimited[:x, :y, :z]
Point.parse("1,2,3\n4,5,6\n7,8,9\n")
  # == [
  #      Point.new(1, 2, 3),
  #      Point.new(4, 5, 6),
  #      Point.new(7, 8, 9)
  #    ]

@param data [String, IO] @return [Array<Struct>]

# File lib/dumb_delimited.rb, line 189
def parse(data)
  parse_each(data).to_a
end
Also aliased as: parse_text
parse_each(data, &block) click to toggle source

Parses a string or IO object one line at a time, yielding a model object for each line.

An Enumerator is returned if no block is given.

@overload parse_each(data, &block)

@param data [String, IO]
@yieldparam model [Struct]
@return [void]

@overload parse_each(data)

@param data [String, IO]
@return [Enumerator<Struct>]
# File lib/dumb_delimited.rb, line 208
def parse_each(data, &block)
  return to_enum(__method__, data) unless block_given?

  csv_each(CSV.new(data, self.options), &block)
end
parse_file(path)
Alias for: read
parse_line(line) click to toggle source

Parses a single delimited line into a model object.

@example

Point = DumbDelimited[:x, :y, :z]
Point.parse_line("1,2,3")  # == Point.new(1, 2, 3)

@param line [String] @return [Struct]

# File lib/dumb_delimited.rb, line 172
def parse_line(line)
  parse_each(line).first
end
parse_text(data)
Alias for: parse
read(path) click to toggle source

Parses a file into an array of model objects. This will load the entire contents of the file into memory, and may not be suitable for large files. To iterate over file contents without loading it all into memory at once, use {read_each}.

@example

# CONTENTS OF FILE "points.csv":
# 1,2,3
# 4,5,6
# 7,8,9

Point = DumbDelimited[:x, :y, :z]
Point.read("points.csv")
  # == [
  #      Point.new(1, 2, 3),
  #      Point.new(4, 5, 6),
  #      Point.new(7, 8, 9)
  #    ]

@param path [String, Pathname] @return [Array<Struct>]

# File lib/dumb_delimited.rb, line 235
def read(path)
  read_each(path).to_a
end
Also aliased as: parse_file
read_each(path, &block) click to toggle source

Parses a file one line at a time, yielding a model object for each line. This avoids loading the entire contents of the file into memory at once.

An Enumerator is returned if no block is given. Note that some Enumerator methods, such as +Enumerator#to_a+, can cause the entire contents of the file to be loaded into memory.

@overload read_each(path, &block)

@param path [String, Pathname]
@yieldparam model [Struct]
@return [void]

@overload read_each(path)

@param path [String, Pathname]
@return [Enumerator<Struct>]
# File lib/dumb_delimited.rb, line 257
def read_each(path, &block)
  return to_enum(__method__, path) unless block_given?

  CSV.open(path, self.options) do |csv|
    csv_each(csv, &block)
  end
end
write(path, models, append: false) click to toggle source

Writes a collection of model objects to a file in delimited format. The previous contents of the file are overwritten, unless append is set to true.

Column headers are written to the file if :write_headers in {options} is set to true and either append is false or the file is empty / non-existent. The column headers will be derived from either the value of :headers in {options} if it is an Array, or otherwise from the columns defined by the model.

@param path [String, Pathname] @param models [Enumerable<Struct>] @param append [Boolean] @return [void]

# File lib/dumb_delimited.rb, line 279
def write(path, models, append: false)
  mode = append ? "a" : "w"
  write_headers = options[:write_headers] && !(append && File.exist?(path) && File.size(path) > 0)
  headers = (!options[:headers].is_a?(Array) && write_headers) ? members : options[:headers]

  CSV.open(path, mode, **options, write_headers: write_headers, headers: headers) do |csv|
    models.each{|model| csv << model }
  end
end

Private Instance Methods

csv_each(csv, &block) click to toggle source
# File lib/dumb_delimited.rb, line 301
def csv_each(csv, &block)
  csv.each do |row|
    row = row.fields if row.is_a?(CSV::Row)
    block.call(self.new(*row))
  end
end