Last active
November 3, 2015 19:45
-
-
Save akoskovacs/31578be903025169e022 to your computer and use it in GitHub Desktop.
Ruby on Rails style database interface for CSV files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HeaderType | |
attr_reader :header | |
ATTRS = {string: :string, int: :int, number: :int, integer: :int } | |
def initialize | |
@header = [] | |
end | |
# Define methods string, integer, etc., | |
# for schema definition dynamically | |
class_eval do | |
ATTRS.each do |attr, type| | |
define_method attr do |name| | |
@header << [type, name] | |
end | |
end | |
end | |
end | |
class CSV | |
def self.create_table(name, &block) | |
# Generate the appropriate class for the schema | |
dync = Class.new do |k| | |
@@db = nil | |
@@table = [] | |
@@header = [] | |
@@rows = [] | |
define_method :initialize do |row| | |
@new_row = row | |
row.each do |k,e| | |
define_singleton_method k do return @new_row[k] end | |
end | |
end | |
define_method :save do | |
return false if @new_row.empty? or @new_row.nil? | |
@@header.each do |t,e| | |
return false if (@new_row[e.to_sym] == nil) | |
end | |
@@rows << @new_row.values | |
@@table << @new_row | |
return true | |
end | |
define_singleton_method :create do |args| | |
k.new(args) | |
end | |
define_singleton_method :pretty_print do | |
max = [] | |
@@rows.each_with_index do |row, i| | |
max[i] = 0 | |
row.map do |col| | |
len = col.to_s.length | |
max[i] = len if (len > max[i]) | |
end | |
max[i] += 2 | |
end | |
sep_line = '+' | |
@@header.each_index do |i| | |
sep_line += ('-' * max[i]) + '+' | |
end | |
@@rows.each do |row| | |
puts sep_line | |
row.each_with_index do |c,i| | |
printf("| %-#{max[i]-2}s ", c) | |
end | |
puts '|' | |
end | |
puts sep_line | |
end | |
define_singleton_method :find do |col, e| | |
arr = [] | |
@@table.each do |r| | |
arr << r if (r[col] == e) | |
end | |
return nil if arr.empty? | |
return arr | |
end | |
define_singleton_method :all do | |
return @@table | |
end | |
define_singleton_method :all_rows do | |
return @@rows | |
end | |
define_singleton_method :read_file do |fname| | |
if @@db.nil? | |
@@db = File.open(fname, 'r'); | |
end | |
@@db.readline | |
@@db.each_line do |l| | |
r = l.chomp.split(/,/) | |
rh = {} | |
rl = [] | |
@@header.each_with_index do |h,i| | |
if h[0] == :int | |
e = r[i].to_i | |
else | |
# remove the leading and closing quotes | |
if (r[i][0] == '"' and r[i][-1] == '"') | |
e = r[i][1..(-2)] | |
else | |
e = r[i] | |
end | |
end | |
rh[h[1]] = e | |
rl << e | |
end | |
@@rows << rl | |
@@table << rh | |
end | |
@@db.close | |
end | |
define_singleton_method :set_header do |hdr| | |
@@header = hdr | |
end | |
end | |
klass = Object.const_set(name.capitalize, dync) | |
h = HeaderType.new | |
block.call(h) | |
hdr = h.header | |
klass.set_header hdr | |
klass.read_file "#{name}.csv" | |
end | |
end | |
# | |
# END OF THE IMPLEMENTATION # | |
# Define csv schema for a person | |
# NOTICE: A person.csv file is mandatory | |
CSV.create_table 'person' do |t| | |
t.string :fname | |
t.string :sname | |
t.int :birth_year | |
t.int :postcode | |
end | |
puts "--- List all persons in the file ---" | |
puts Person.all # list all person from file | |
puts "--- Find someone from 1990 ---" | |
puts Person.find(:birth_year, 1990) # find | |
puts "--- Create a new person ---" | |
p = Person.create(fname: 'John', sname: 'Doe', birth_year: 1991, postcode: 2092) | |
puts p.inspect | |
puts "--- Save '#{p.fname} #{p.sname}' to the database ---" | |
p.save | |
puts "--- Pretty print the new table ---" | |
puts Person.pretty_print |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment