Module: Hecks::Adapters::InMemoryOrdering
- Defined in:
- lib/hecks/adapters/driven/in_memory_ordering.rb
Overview
SHARED BY every adapter that holds decoded Ruby records rather than running real SQL (Memory, Lambda, Heki) — the identical dotted-path value-object member-picking Postgres/Sqlite/D1's own order_expression does (numeric member wins, else the one-field convention "value"), just walked in Ruby instead of compiled to a JSONB/json_extract path, because there is no query engine underneath any of these three to hide that walk inside.
Class Method Summary collapse
-
.ordered(records, aggregate:, order_by:, direction:) ⇒ Object
order_by IS A RUNTIME VALUE (an HTTP query param, in the console's case), not framework-authored bluebook source — see postgres.rb's own all for the full reasoning.
- .sortable_path(aggregate, field) ⇒ Object
Class Method Details
.ordered(records, aggregate:, order_by:, direction:) ⇒ Object
order_by IS A RUNTIME VALUE (an HTTP query param, in the console's case), not framework-authored bluebook source — see postgres.rb's own all for the full reasoning. Whitelisted the identical way before FieldPath.dig ever runs.
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/hecks/adapters/driven/in_memory_ordering.rb', line 23 def ordered(records, aggregate:, order_by:, direction:) return records unless order_by name = order_by.to_s.split(".").first raise Runtime::WiringError, "#{aggregate.name} has no attribute #{order_by.inspect} to order by" unless aggregate.lifecycle&.field.to_s == name || aggregate.attribute(name) path = sortable_path(aggregate, order_by) spec = QuerySpecification::Common::OrderBy.new(field: order_by, direction: direction) Ports::Query::Ordering.apply(records, spec, nil, identity: ->(record) { record.id.to_s }) do |record| Ports::Query::InMemory.comparable(QuerySpecification::FieldPath.dig(record, path)) end end |
.sortable_path(aggregate, field) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/hecks/adapters/driven/in_memory_ordering.rb', line 36 def sortable_path(aggregate, field) name, *path = field.to_s.split(".") return field.to_s unless path.empty? attribute = aggregate.attribute(name) return field.to_s if aggregate.lifecycle&.field.to_s == name || attribute.nil? vo = aggregate.value_object(attribute.type) return field.to_s unless vo member = vo.attributes.find { |a| %w[Integer Float].include?(a.type) }&.name || "value" "#{name}.#{member}" end |