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.
|
||||
# @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,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…
Reference in New Issue