class Kwipper::Model
Constants
- DB_FILE_NAME
- DB_NAME
- ID_COLUMN
- UnknownAttribute
Attributes
columns[R]
id[RW]
Public Class Methods
all(statement = "SELECT * FROM
click to toggle source
Get records from a single table and instantiate them
# File lib/kwipper/model.rb, line 33 def all(statement = "SELECT * FROM #{table_name}") sql(statement).each_with_object [] do |attrs, models| models << new(attr_array_to_hash attrs) end end
column(name, type)
click to toggle source
Declare columns in the model subclass in the same order the columns were created in the table. This lets us instantiate model objects from arrays of field values from the db. ID columns is defaulted.
# File lib/kwipper/model.rb, line 17 def column(name, type) @columns ||= { ID_COLUMN => :to_i } @columns[name] = type attr_accessor name end
count(statement = "SELECT COUNT(id) FROM
click to toggle source
# File lib/kwipper/model.rb, line 74 def count(statement = "SELECT COUNT(id) FROM #{table_name}") sql(statement).first.first end
create(attrs)
click to toggle source
# File lib/kwipper/model.rb, line 47 def create(attrs) db_attrs = attrs.map { |k, v| normalize_value_for_db v, columns[k] } unless attrs.key? 'id' id = generate_id attrs['id'] = id db_attrs = [id, *db_attrs] end sql "INSERT INTO #{table_name} VALUES(#{db_attrs.join ', '})" new attrs end
db()
click to toggle source
# File lib/kwipper/model.rb, line 10 def db @db ||= SQLite3::Database.open File.join(Kwipper::ROOT, 'db', DB_FILE_NAME) end
destroy(id)
click to toggle source
# File lib/kwipper/model.rb, line 64 def destroy(id) sql "DELETE FROM #{table_name} WHERE id=#{id}" end
exists?(id)
click to toggle source
# File lib/kwipper/model.rb, line 68 def exists?(id) id = normalize_value_for_db id, columns['id'] result = sql "SELECT id FROM #{table_name} WHERE id = #{id} LIMIT 1" result.first && result.first.any? end
find(id)
click to toggle source
# File lib/kwipper/model.rb, line 39 def find(id) where(id: id).first end
new(attrs = {})
click to toggle source
Takes a hash of model attributes and sets them via accessors if they exists
# File lib/kwipper/model.rb, line 82 def initialize(attrs = {}) attrs.keys.each do |name| if self.class.columns.keys.include? name type = self.class.columns[name] send "#{name}=", attrs[name].send(type) else raise UnknownAttribute, "#{name} for #{self}" end end end
sql(cmd)
click to toggle source
All SQL statements should be executed through this method
# File lib/kwipper/model.rb, line 25 def sql(cmd) start_time = Time.now.to_f db.execute(cmd).tap do log.debug "#{cmd.red} in #{sprintf '%.8f', Time.now.to_f - start_time}s" end end
update(id, attrs)
click to toggle source
# File lib/kwipper/model.rb, line 60 def update(id, attrs) sql "UPDATE #{table_name} SET #{hash_to_key_vals attrs} WHERE id=#{id}" end
where(attrs)
click to toggle source
# File lib/kwipper/model.rb, line 43 def where(attrs) all "SELECT * FROM #{table_name} WHERE #{hash_to_key_vals attrs}" end
Private Class Methods
attr_array_to_hash(attrs)
click to toggle source
# File lib/kwipper/model.rb, line 148 def attr_array_to_hash(attrs) attrs.each_with_index.inject({}) do |hash, (attr_val, i)| hash.merge! @columns.keys[i] => attr_val end end
generate_id()
click to toggle source
# File lib/kwipper/model.rb, line 142 def generate_id max_id_plus_1 = "SELECT (id + 1) as id FROM #{table_name} ORDER BY id DESC LIMIT 1" result = sql(max_id_plus_1).first result && result.first ? result.first : 1 end
hash_to_key_vals(hash)
click to toggle source
Turn a hash of attributes into a comma separated string that's safe to use in a SQL statement (non int values are quoted). TODO: add SQL sanitation.
# File lib/kwipper/model.rb, line 157 def hash_to_key_vals(hash) hash.inject [] do |a, (k, v)| v = normalize_value_for_db v, columns[k] a << "#{k}=#{v}" end.join ', ' end
normalize_value_for_db(value, type)
click to toggle source
Non int values should be quoted when putting in a SQL statement
# File lib/kwipper/model.rb, line 165 def normalize_value_for_db(value, type) case type when :to_i value.to_i else "\"#{value}\"" end end
table_name()
click to toggle source
# File lib/kwipper/model.rb, line 138 def table_name Inflect.new(name).demodulize.pluralize.underscore end
Public Instance Methods
destroy(id)
click to toggle source
# File lib/kwipper/model.rb, line 115 def destroy(id) self.class.destroy id end
save()
click to toggle source
Saves model instance to the database
# File lib/kwipper/model.rb, line 94 def save if id self.class.update id, attrs_for_db else self.class.create a = attrs_for_db @id ||= a['id'] end true rescue SQLite3::SQLException => e log.warn e.message false end
sql(statement)
click to toggle source
# File lib/kwipper/model.rb, line 119 def sql(statement) self.class.sql statement end
update(attrs)
click to toggle source
# File lib/kwipper/model.rb, line 108 def update(attrs) self.class.update id, attrs true rescue KeyError => e false end
Private Instance Methods
attrs_for_db()
click to toggle source
# File lib/kwipper/model.rb, line 125 def attrs_for_db self.class.columns.each_with_object({}) do |(name, _), attrs| value = send name value = generate_id if name == ID_COLUMN && value.nil? attrs[name] = value unless value.nil? end end
generate_id()
click to toggle source
# File lib/kwipper/model.rb, line 133 def generate_id self.class.generate_id end