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