This repository has been archived on 2024-06-24. You can view files and clone it, but cannot push or open issues or pull requests.
ace-of-base/lib/ace_of_base/query.rb

76 lines
1.6 KiB
Ruby
Raw Normal View History

2019-07-10 21:46:42 +12:00
# frozen_string_literal: true
module AceOfBase
# A query builder for querying our data.
class Query
INVALID_FIELD_MESSAGE = 'Field %s is not a valid field name'
def initialize(storage)
@fields = []
@order_bys = []
@filters = []
@storage = storage
end
def select(*fields)
ensure_valid_fields!(fields)
@fields = fields
self
end
def order_by(*fields)
ensure_valid_fields!(fields)
@order_bys = fields
self
end
def filter(field, value)
ensure_valid_fields!([field])
@filters << [field, value]
self
end
def execute
@storage
.select(&method(:select_with_filters))
.sort(&method(:sort_with_order_bys))
.map(&method(:take_fields))
end
private
attr_reader :fields, :order_bys, :filters, :storage
def ensure_valid_fields!(fields)
fields.each do |field|
raise ArgumentError, format(INVALID_FIELD_MESSAGE, field) \
unless Record::ATTRIBUTES.include?(field.to_sym)
end
end
def take_fields(record)
selected_fields.map { |field| record.public_send(field) }
end
def sort_with_order_bys(lhs, rhs)
@order_bys
.lazy
.map { |attr| lhs.public_send(attr) <=> rhs.public_send(attr) }
.find(-> { 0 }, &:nonzero?)
end
def select_with_filters(record)
@filters.all? do |(key, value)|
record.public_send(key) == value
end
end
def selected_fields
return Record::ATTRIBUTES if fields.empty?
fields
end
end
end