Added SELECT object mapping, convenience methods, fixed weakref usage after object death
This commit is contained in:
parent
22c4722a8c
commit
b35d4926b1
55
lib/lpgar.rb
55
lib/lpgar.rb
|
@ -65,20 +65,53 @@ module LPGAR
|
||||||
|
|
||||||
# Return either an existing Record or create a new one.
|
# Return either an existing Record or create a new one.
|
||||||
# @param data [Hash{String => Object}] row data
|
# @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
|
check_instantiable
|
||||||
ident = Digest::MD5.hexdigest(data.values_at(*cols_pk).join)
|
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].sync
|
||||||
@instances[ident]
|
@instances[ident]
|
||||||
end
|
end
|
||||||
|
|
||||||
new_record = super(data)
|
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)
|
track_instance(new_record)
|
||||||
new_record
|
new_record
|
||||||
end
|
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
|
# Change row identity
|
||||||
# Should not be called directly in most cases.
|
# Should not be called directly in most cases.
|
||||||
# @param original [String] original row identity
|
# @param original [String] original row identity
|
||||||
|
@ -91,15 +124,15 @@ module LPGAR
|
||||||
# Create sync query.
|
# Create sync query.
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def sync_query
|
def sync_query
|
||||||
return @_memo_query if @_memo_query
|
return @sync_query if @sync_query
|
||||||
|
|
||||||
selector = @cols_pk.map.with_index do |pk, index|
|
selector = @cols_pk.map.with_index do |key, index|
|
||||||
"#{pk} = $#{index + 1}"
|
"#{key} = $#{index + 1}"
|
||||||
end.join " AND "
|
end.join " AND "
|
||||||
@_memo_query = <<~QUERY
|
@sync_query = <<~QUERY
|
||||||
SELECT * FROM #{@table_name}
|
SELECT * FROM #{@table_name}
|
||||||
WHERE #{selector}
|
WHERE #{selector}
|
||||||
LIMIT 1
|
LIMIT 1;
|
||||||
QUERY
|
QUERY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -139,6 +172,8 @@ module LPGAR
|
||||||
end
|
end
|
||||||
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
# Check if Record is properly set up.
|
# Check if Record is properly set up.
|
||||||
# @raise [StandardError] rasied if class is not properly set up
|
# @raise [StandardError] rasied if class is not properly set up
|
||||||
def check_instantiable
|
def check_instantiable
|
||||||
|
@ -166,7 +201,7 @@ module LPGAR
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create a new record by "INSERT"
|
# Create a new record by "INSERT"
|
||||||
def create(record)
|
def insert_query(record)
|
||||||
recbody = record.instance_variable_get("@data")
|
recbody = record.instance_variable_get("@data")
|
||||||
# @sg-ignore
|
# @sg-ignore
|
||||||
conn.exec(<<~QUERY, recbody.values)
|
conn.exec(<<~QUERY, recbody.values)
|
||||||
|
@ -336,7 +371,7 @@ module LPGAR
|
||||||
@conn = conn
|
@conn = conn
|
||||||
@instances = {}
|
@instances = {}
|
||||||
end
|
end
|
||||||
new_class.class_exec(&block)
|
new_class.class_exec(&block) if block
|
||||||
new_class
|
new_class
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
spec.name = "lpgar"
|
spec.name = "lpgar"
|
||||||
spec.version = "0.1"
|
spec.version = "0.2"
|
||||||
spec.summary = "Lightweight Postgres Active Record"
|
spec.summary = "Lightweight Postgres Active Record"
|
||||||
spec.description = <<~DESC
|
spec.description = <<~DESC
|
||||||
Lightweight implementation of Active Record pattern for Postgres.
|
Lightweight implementation of Active Record pattern for Postgres.
|
||||||
|
|
Loading…
Reference in New Issue