Module: Plushie::DataQuery

Defined in:
lib/plushie/data.rb

Overview

Query pipeline for in-memory record collections. Pure functions supporting filter, search, sort, group, and pagination.

All operations are applied in order: filter, search, sort, then paginate. Grouping is applied to the paginated results.

Examples:

records = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 },
  { name: "Carol", age: 35 }
]

result = Plushie::Data.query(records,
  filter: ->(r) { r[:age] > 24 },
  sort: [:asc, :name],
  page: 1,
  page_size: 10
)

result[:entries]  #=> all three records sorted by name
result[:total]    #=> 3

Class Method Summary collapse

Class Method Details

.query(records, filter: nil, search: nil, sort: nil, group: nil, page: 1, page_size: 25) ⇒ Hash

Queries a list of records with optional filtering, searching, sorting, grouping, and pagination.

Parameters:

  • records (Array<Hash>)

    the records to query

  • filter (Proc, nil) (defaults to: nil)

    a proc that returns true for records to keep

  • search (Array, nil) (defaults to: nil)

    a [fields, query_string] pair; fields is an array of hash keys to search; query_string is case-insensitive substring-matched

  • sort (Array, Array<Array>, nil) (defaults to: nil)

    a [direction, field] pair or array of pairs. Direction is +:asc+ or +:desc+.

  • group (Object, nil) (defaults to: nil)

    a hash key to group paginated results by

  • page (Integer) (defaults to: 1)

    page number (1-based, default: 1)

  • page_size (Integer) (defaults to: 25)

    records per page (default: 25)

Returns:

  • (Hash)

    with keys :entries, :total, :page, :page_size, :groups



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/plushie/data.rb', line 42

def self.query(records, filter: nil, search: nil, sort: nil, group: nil, page: 1, page_size: 25)
  result = records
  result = result.select(&filter) if filter
  result = apply_search(result, search) if search
  result = apply_sort(result, sort) if sort

  total = result.length
  offset = (page - 1) * page_size
  entries = result[offset, page_size] || []

  groups = if group
    entries.group_by { |r| r[group] }
  end

  {entries: entries, total: total, page: page, page_size: page_size, groups: groups}
end