Class: Feet::Model::SQLiteModel

Inherits:
Object
  • Object
show all
Defined in:
lib/feet/sqlite_model.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = nil) ⇒ SQLiteModel

Returns a new instance of SQLiteModel.



9
10
11
# File 'lib/feet/sqlite_model.rb', line 9

def initialize(data = nil)
  @hash = data
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/feet/sqlite_model.rb', line 118

def method_missing(method, *args)
  # Check for getter
  if @hash[method.to_s]
    self.class.define_method(method) do
      self[method]
    end
    return send(method)
  end

  # Check for setters
  if method.to_s[-1..-1] == '='
    field = method.to_s[0..-2]
    self.class.class_eval do
      define_method(method) do |value|
        self[field] = value
      end
    end
    return self.send(method, args[0])
  end

  super
end

Class Method Details

.allObject



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/feet/sqlite_model.rb', line 99

def self.all
  keys = schema.keys
  rows = DB.execute <<~SQL
    SELECT * FROM #{table}
  SQL

  rows.map do |row|
    data = Hash[keys.zip row]
    self.new data
  end
end

.countObject



111
112
113
114
115
116
# File 'lib/feet/sqlite_model.rb', line 111

def self.count
  db_result = DB.execute <<~SQL
    SELECT COUNT(*) FROM #{table};
  SQL
  db_result[0][0]
end

.create(initial_hash) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/feet/sqlite_model.rb', line 41

def self.create(initial_hash)
  # Get initial_hash and schema keys without ids and map initial_hash to schema keys
  initial_hash.delete 'id'
  keys = schema.keys - ['id']
  sql_values = keys.map do |key|
    initial_hash[key] ? to_sql(initial_hash[key]) : 'null'
  end

  # Insert values into table
  DB.execute <<~SQL
    INSERT INTO #{table} (#{keys.join ','}) VALUES (#{sql_values.join ','});
  SQL

  # Build and return the new table entry
  raw_values = keys.map { |k| initial_hash[k] }
  data = Hash[keys.zip raw_values]

  # Get the latest id
  sql = 'SELECT last_insert_rowid();'
  data['id'] = DB.execute(sql)[0][0]

  self.new data
end

.find(id) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/feet/sqlite_model.rb', line 65

def self.find(id)
  keys = schema.keys
  response = DB.execute <<~SQL
    SELECT #{keys.join ','} FROM #{table} WHERE id = #{id}
  SQL
  return nil unless response[0]

  data = Hash[keys.zip response[0]]
  self.new data
end

.schemaObject



17
18
19
20
21
22
23
24
25
26
# File 'lib/feet/sqlite_model.rb', line 17

def self.schema
  return @schema if @schema

  @schema = {}
  DB.table_info(table) do |row|
    @schema[row['name']] = row['type']
  end

  @schema
end

.tableObject



13
14
15
# File 'lib/feet/sqlite_model.rb', line 13

def self.table
  Feet.to_snake_case name # name = method to return the class name, ex: MyName
end

.to_sql(value) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/feet/sqlite_model.rb', line 28

def self.to_sql(value)
  case value
  when NilClass
    'null'
  when Numeric
    value.to_s
  when String
    "'#{value}'"
  else
    raise "Can't convert #{value.class} to SQL."
  end
end

Instance Method Details

#[](name) ⇒ Object



76
77
78
# File 'lib/feet/sqlite_model.rb', line 76

def [](name)
  @hash[name.to_s]
end

#[]=(key, value) ⇒ Object



80
81
82
# File 'lib/feet/sqlite_model.rb', line 80

def []=(key, value)
  @hash[key] = value
end

#save!Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/feet/sqlite_model.rb', line 84

def save!
  return nil unless @hash['id']

  hash_map = @hash.keys.map do |key|
    "#{key} = #{self.class.to_sql(@hash[key])}"
  end

  DB.execute <<~SQL
    UPDATE #{self.class.table}
    SET #{hash_map.join ','}
    WHERE id = #{@hash['id']};
  SQL
  @hash
end