Browse Source

Added SELECT object mapping, convenience methods, fixed weakref usage after object death

master
Yessiest 7 months ago
parent
commit
b35d4926b1
  1. 55
      lib/lpgar.rb
  2. 2
      lpgar.gemspec

55
lib/lpgar.rb

@ -65,20 +65,53 @@ module LPGAR
# Return either an existing Record or create a new one.
# @param data [Hash{String => Object}] row data
def new(data)
# @param syncless [Boolean] do not perform any communication with PG
# @return [Object] new record object
def new(data, syncless: false)
check_instantiable
ident = Digest::MD5.hexdigest(data.values_at(*cols_pk).join)
if @instances[ident]
if @instances[ident] and @instances[ident].weakref_alive?
@instances[ident].sync
@instances[ident]
end
new_record = super(data)
create(new_record) unless new_record.sync
unless syncless
synced = new_record.sync
insert_query(new_record) unless synced
end
track_instance(new_record)
new_record
end
# Explicitly create a new record. Returns nil if exists.
# @param data [Hash{String => Object}] row data
# @return [(Object,nil)] new record object or nil if exists
def create(data)
instance = new(data, syncless: true)
return if instance.sync
insert_query(instance)
instance
end
# Explicitly request an existing record. Returns nil if doesn't exist.
# @param data [Hash{String => Object}] row data
# @return [(Object,nil)] new record object or nil if doesn't exist.
def get(data)
instance = new(data, syncless: true)
instance if instance.sync
end
# Map returned rows from a query to an array of objects of this table.
# @param query [String] raw postgresql query
# @return [Array(Object)] array of records of this table
def map(query)
conn.exec(query).map do |row|
new(row, syncless: true)
end
end
# Change row identity
# Should not be called directly in most cases.
# @param original [String] original row identity
@ -91,15 +124,15 @@ module LPGAR
# Create sync query.
# @return [String]
def sync_query
return @_memo_query if @_memo_query
return @sync_query if @sync_query
selector = @cols_pk.map.with_index do |pk, index|
"#{pk} = $#{index + 1}"
selector = @cols_pk.map.with_index do |key, index|
"#{key} = $#{index + 1}"
end.join " AND "
@_memo_query = <<~QUERY
@sync_query = <<~QUERY
SELECT * FROM #{@table_name}
WHERE #{selector}
LIMIT 1
LIMIT 1;
QUERY
end
@ -139,6 +172,8 @@ module LPGAR
end
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
private
# Check if Record is properly set up.
# @raise [StandardError] rasied if class is not properly set up
def check_instantiable
@ -166,7 +201,7 @@ module LPGAR
end
# Create a new record by "INSERT"
def create(record)
def insert_query(record)
recbody = record.instance_variable_get("@data")
# @sg-ignore
conn.exec(<<~QUERY, recbody.values)
@ -336,7 +371,7 @@ module LPGAR
@conn = conn
@instances = {}
end
new_class.class_exec(&block)
new_class.class_exec(&block) if block
new_class
end

2
lpgar.gemspec

@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "lpgar"
spec.version = "0.1"
spec.version = "0.2"
spec.summary = "Lightweight Postgres Active Record"
spec.description = <<~DESC
Lightweight implementation of Active Record pattern for Postgres.

Loading…
Cancel
Save