Skip to content

Instantly share code, notes, and snippets.

@fguillen
Last active October 5, 2024 18:56
Show Gist options
  • Save fguillen/57ef5af51c574076c0aa5930f430ebd9 to your computer and use it in GitHub Desktop.
Save fguillen/57ef5af51c574076c0aa5930f430ebd9 to your computer and use it in GitHub Desktop.
require "sqlite3"
module ActiveRecord
class Mini
attr_reader :attributes
def initialize(attributes = {})
@attributes = attributes
end
def save
if id.nil?
sql = <<~SQL
insert into
#{self.class.table_name}
(#{@attributes.keys.join(", ")})
values
(#{@attributes.size.times.map { |_| "?" }.join(", ")})
SQL
self.class.execute(sql, @attributes.values)
@attributes["id"] = self.class.connection.last_insert_row_id
else
sql = <<~SQL
update
#{self.class.table_name}
set #{@attributes.keys.map { |key| "#{key} = ?" }.join(", ")}
where id = ?
SQL
self.class.execute(
sql,
@attributes.values,
id
)
end
end
def reload
@attributes = self.class.find(id).attributes
end
def delete
self.class.execute("delete from #{self.class.table_name} where id = ?", id)
end
def self.table_name
"#{name.downcase}s"
end
def self.column_names
columns.map { |column| column["name"] }
end
def self.columns
@columns ||= self.execute("pragma table_info(#{table_name});")
end
def self.connection
@connection ||=
begin
connection = SQLite3::Database.new "#{__dir__}/data.db"
connection.results_as_hash = true
connection
end
end
def self.find(id)
data = self.execute("select * from #{table_name} where id = ?", id).first
return nil if data.nil?
self.new(data)
end
def self.execute(*args)
puts "SQL: #{args}"
if args.size > 1
connection.prepare(args[0]).execute(args[1..])
else
connection.execute(args[0])
end
end
def self.inherited(subclass)
subclass.class_eval do
column_names.each do |column_name|
define_method(column_name) do
@attributes[column_name]
end
define_method("#{column_name}=") do |value|
@attributes[column_name] = value
end
end
end
end
end
end
class User < ActiveRecord::Mini
end
p User.table_name # => "users"
p User.column_names # => ["id", "name"]
user = User.new(name: "John")
user.save
p user.id # => 1
user.reload
p user.name # => "John"
user.name = "Jane"
user.save
user.reload
p user.name # => "Jane"
user = User.find(1)
p user.name # => "Jane"
user.delete
p User.find(1) # => nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment