module CSVInteractable::ClassMethods

Public Instance Methods

all_records(mode: 'r') { |row| ... } click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 132
def all_records(mode: 'r', &block)
  records = []
  CSV.open(self.storage_path, mode, headers: true, header_converters: [:symbol, :downcase]) do |csv|
    csv.each do |row|
      prep_row_read!(row)
      records << row if yield(row)
    end
  end
  records
end
append_row(data, should_add_id: true) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 143
def append_row(data, should_add_id: true)
  row = data.reduce(CSV::Row.new([],[])) do |mem, (k,v)|
    data_type = get_schema[k]
    adapter = get_adapter(data_type)
    mem[k] = adapter.write(v)
    mem
  end
  begin
    ret_val = nil
    self.mutate_csv(:append) do |csv, last_id|
      if should_add_id
        ret_val = last_id + 1
        row[:id] = get_adapter(:integer).write(last_id + 1)
      end
      csv << row
    end
    ret_val
  rescue => e
    File.delete("#{self.storage_path}.bak.csv") if File.exist?("#{self.storage_path}.bak.csv")
    raise e
    false
  end
end
delete_row(data) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 188
def delete_row(data)
  begin
    self.mutate_csv(:mutate) do |csv, bak_row|
      if bak_row[:id] != data[:id]
        prep_row_write!(bak_row)
        csv << bak_row
      end
    end
    true
  rescue
    File.delete("#{self.storage_path}.bak.csv")
    false
  end
end
each_record(mode: 'r') { |row| ... } click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 123
def each_record(mode: 'r', &block)
  CSV.open(self.storage_path, mode, headers: true, header_converters: [:symbol, :downcase]) do |csv|
    csv.each do |row|
      prep_row_read!(row)
      yield(row)
    end
  end
end
find_record(mode: 'r') { |row| ... } click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 113
def find_record(mode: 'r', &block)
  CSV.open(self.storage_path, mode, headers: true, header_converters: [:symbol, :downcase]) do |csv|
    csv.each do |row|
      prep_row_read!(row)
      return row if yield(row)
    end
    return nil
  end
end
get_adapter(data_type) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 76
def get_adapter(data_type)
  case data_type
  when :integer
    LocalModel::IntegerAdapter
  when :boolean
    LocalModel::BooleanAdapter
  when :float
    LocalModel::FloatAdapter
  when :datetime
    LocalModel::DatetimeAdapter
  when :string
    LocalModel::StringAdapter
  else
    raise ArgumentError.new("Incorrect datatype entered (#{data_type})")
  end
end
mutate_csv(option=:mutate) { |csv_orig, bak_row| ... } click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 13
def mutate_csv(option=:mutate,&block)
  while File.exist?("#{self.storage_path}.bak.csv")
    r = @@rand.rand / 10.0
    sleep(r)
  end
  rand_val = @@rand.rand(1000000)
  f = File.new("#{self.storage_path}-#{rand_val}.prep", 'w')
  f.close
  r = @@rand.rand / 10.0
  sleep(r)

  if File.exist?("#{self.storage_path}.bak.csv") || Dir["#{self.storage_path}-*.prep"].length > 1
    File.delete("#{self.storage_path}-#{rand_val}.prep")
    if @@rand.rand(2) == 1
      sleep(0.5)
    end
    mutate_csv
    return
  else
    File.delete("#{self.storage_path}-#{rand_val}.prep")
    last_id = 0
    CSV.open("#{self.storage_path}.bak.csv", 'wb', headers: self.get_schema.keys.map(&:to_s), write_headers: true, header_converters: [:symbol, :downcase]) do |csv_bak|
      CSV.open(self.storage_path, 'r', headers: true, header_converters: [:symbol, :downcase]) do |csv_orig|
        csv_orig.each do |row|
          csv_bak << row
          last_id = get_adapter(:integer).read(row[:id])
        end
      end
    end
    if option == :mutate
      CSV.open("#{self.storage_path}.bak.csv", 'r', headers: true, header_converters: [:symbol, :downcase]) do |csv_bak|
        CSV.open(self.storage_path, 'w', headers: self.get_schema.keys.map(&:to_s), write_headers: true,  header_converters: [:symbol, :downcase]) do |csv_orig|
          csv_bak.each do |bak_row|
            prep_row_read!(bak_row)
            yield(csv_orig, bak_row)
          end
        end
      end
    else
      CSV.open(self.storage_path, 'a', headers: true, header_converters: [:symbol, :downcase]) do |csv|
        yield(csv, last_id)
      end
    end
    File.delete("#{self.storage_path}.bak.csv")
  end
end
mutate_row(data) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 167
def mutate_row(data)
  begin
    self.mutate_csv(:mutate) do |csv, bak_row|
      if bak_row[:id] == data[:id]
        data.each do |k,v|
          bak_row[k] = data[k]
        end
        prep_row_write!(bak_row)
        csv << bak_row
      else
        prep_row_write!(bak_row)
        csv << bak_row
      end
    end
    true
  rescue => e
    File.delete("#{self.storage_path}.bak.csv")
    false
  end
end
new_from_record(row) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 69
def new_from_record(row)
  formatted_hash = read_from_record(row)
  inst = self.new(**formatted_hash)
  inst.id = formatted_hash[:id]
  inst
end
prep_row_read!(row) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 93
def prep_row_read!(row)
  row_hash = row.to_h
  row_hash.each do |k,v|
    data_type = get_schema[k]
    adapter = get_adapter(data_type)
    row[k] = adapter.read(v)
  end
  row
end
prep_row_write!(row) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 103
def prep_row_write!(row)
  row_hash = row.to_h
  row_hash.each do |k,v|
    data_type = get_schema[k]
    adapter = get_adapter(data_type)
    row[k] = adapter.write(v)
  end
  row
end
read_from_record(row) click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 60
def read_from_record(row)
  row = row.to_h
  row.reduce({}) do |mem, (k,v)|
    data_type = self.get_schema[k]
    adapter = get_adapter[data_type]
    mem[k] = adapter.read(v)
  end
end
write_headers() click to toggle source
# File lib/local_model/concerns/csv_interactable.rb, line 7
def write_headers
  CSV.open(self.storage_path, 'wb') do |csv|
    csv << columns.map(&:to_s)
  end
end