Class: Kwipper::Model
- Inherits:
-
Object
show all
- Defined in:
- lib/kwipper/model.rb
Constant Summary
collapse
- DB_NAME =
'kwipper'
- DB_FILE_NAME =
"#{DB_NAME}.db"
- ID_COLUMN =
'id'
- UnknownAttribute =
Class.new ArgumentError
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(attrs = {}) ⇒ Model
Takes a hash of model attributes and sets them via accessors if they exists
82
83
84
85
86
87
88
89
90
91
|
# 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
|
Class Attribute Details
.columns ⇒ Object
Returns the value of attribute columns.
22
23
24
|
# File 'lib/kwipper/model.rb', line 22
def columns
@columns
end
|
Instance Attribute Details
#id ⇒ Object
Returns the value of attribute id.
79
80
81
|
# File 'lib/kwipper/model.rb', line 79
def id
@id
end
|
Class Method Details
.all(statement = "SELECT * FROM #{table_name}") ⇒ Object
Get records from a single table and instantiate them
33
34
35
36
37
|
# 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
|
.attr_array_to_hash(attrs) ⇒ Object
148
149
150
151
152
|
# 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
|
.column(name, type) ⇒ Object
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.
17
18
19
20
21
|
# 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 #{table_name}") ⇒ Object
74
75
76
|
# File 'lib/kwipper/model.rb', line 74
def count(statement = "SELECT COUNT(id) FROM #{table_name}")
sql(statement).first.first
end
|
.create(attrs) ⇒ Object
47
48
49
50
51
52
53
54
55
56
57
58
|
# 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 ⇒ Object
10
11
12
|
# File 'lib/kwipper/model.rb', line 10
def db
@db ||= SQLite3::Database.open File.join(Kwipper::ROOT, 'db', DB_FILE_NAME)
end
|
.destroy(id) ⇒ Object
64
65
66
|
# File 'lib/kwipper/model.rb', line 64
def destroy(id)
sql "DELETE FROM #{table_name} WHERE id=#{id}"
end
|
.exists?(id) ⇒ Boolean
68
69
70
71
72
|
# 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) ⇒ Object
39
40
41
|
# File 'lib/kwipper/model.rb', line 39
def find(id)
where(id: id).first
end
|
.generate_id ⇒ Object
142
143
144
145
146
|
# 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) ⇒ Object
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.
157
158
159
160
161
162
|
# 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) ⇒ Object
Non int values should be quoted when putting in a SQL statement
165
166
167
168
169
170
171
|
# 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
|
.sql(cmd) ⇒ Object
All SQL statements should be executed through this method
25
26
27
28
29
30
|
# 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
|
.table_name ⇒ Object
138
139
140
|
# File 'lib/kwipper/model.rb', line 138
def table_name
Inflect.new(name).demodulize.pluralize.underscore
end
|
.update(id, attrs) ⇒ Object
60
61
62
|
# 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) ⇒ Object
43
44
45
|
# File 'lib/kwipper/model.rb', line 43
def where(attrs)
all "SELECT * FROM #{table_name} WHERE #{hash_to_key_vals attrs}"
end
|
Instance Method Details
#destroy(id) ⇒ Object
115
116
117
|
# File 'lib/kwipper/model.rb', line 115
def destroy(id)
self.class.destroy id
end
|
#save ⇒ Object
Saves model instance to the database
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# 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) ⇒ Object
119
120
121
|
# File 'lib/kwipper/model.rb', line 119
def sql(statement)
self.class.sql statement
end
|
#update(attrs) ⇒ Object
108
109
110
111
112
113
|
# File 'lib/kwipper/model.rb', line 108
def update(attrs)
self.class.update id, attrs
true
rescue KeyError => e
false
end
|