Documentation
¶
Overview ¶
Package ransack is a pure-Go (CGO=0), MRI-faithful reimplementation of the Ruby "ransack" gem: a search/filter query builder.
A Ransack search is expressed as a "q" params hash whose keys encode an attribute and a predicate, for example:
q := map[string]any{
"name_cont": "foo", // name LIKE '%foo%'
"age_gteq": 18, // age >= 18
"role_in": []any{"admin", "editor"},
"s": "name asc",
}
search := ransack.New(ctx, q)
results, _ := search.Result(&ransack.MemoryBackend{Records: rows})
New parses the hash into a Search: a tree of conditions (Search.Root), a list of Sorts and a Distinct flag. Parsing strips the predicate suffix using the longest matching predicate, splits multi-attribute keys on the _or_ / _and_ combinators, resolves association prefixes and validates every attribute against the Context allowlist (ActiveRecord's ransackable_attributes seam).
Predicates include eq/not_eq, lt/lteq/gt/gteq, cont/not_cont/i_cont, start/ end, matches/does_not_match, in/not_in, the boolean-flag predicates true/false/null/not_null/present/blank and the _any/_all compounds of every scalar predicate.
Application is a seam. A Backend turns a Search into results; the rbgo/ ActiveRecord binding implements it as SQL, while the built-in MemoryBackend (and Search.Match / Search.Apply) evaluate the search in memory so the engine is testable and usable without an ORM.
The intended Ruby surface is Model.ransack(q).result, with predicate suffixes, s/sorts ordering, distinct and g[] grouped conditions all supported.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Attr ¶
Attr is a searchable attribute reference. Path holds the association segments (empty for a direct attribute) and Name is the final column.
type Backend ¶
type Backend interface {
// Result evaluates the search and returns its result set.
Result(s *Search) (any, error)
}
Backend is the application seam. A Search describes what to fetch; a Backend turns that description into results. The rbgo/ActiveRecord binding implements Backend by translating the condition tree into SQL WHERE/JOIN clauses and the sorts into ORDER BY. MemoryBackend is the built-in, ORM-free implementation.
type Condition ¶
type Condition struct {
// Key is the original params key that produced this condition.
Key string
// Attributes are the attributes tested by this condition.
Attributes []Attr
// Combinator joins multiple attributes ("or"/"and"); empty when there is
// a single attribute.
Combinator string
// Predicate is the test applied to each attribute.
Predicate *Predicate
// Values are the (blank-filtered) condition values.
Values []any
}
Condition is a parsed Ransack condition: one or more attributes tested with a single predicate against one or more values. When more than one attribute is present (the a_or_b / a_and_b grammar) Combinator ("or"/"and") joins them.
type Context ¶
type Context struct {
// Attributes is the set of searchable/sortable columns. Nil means open.
Attributes []string
// Associations maps an association name to its own Context.
Associations map[string]*Context
}
Context is the allowlist seam. It mirrors ActiveRecord's ransackable_attributes / ransackable_associations: only whitelisted attributes and associations may be searched or sorted. This keeps a search engine safe when it is driven by untrusted params.
A Context with a nil Attributes slice is "open" and allows every attribute name. Associations is a map from association name to the Context describing that associated model.
func NewContext ¶
NewContext returns a Context allowing the given attributes. With no arguments it returns an open Context that allows every attribute.
type Group ¶
Group is a tree node combining conditions and nested groups with a boolean combinator ("and"/"or").
type MemoryBackend ¶
MemoryBackend evaluates a Search over an in-memory slice of records using the built-in evaluator. Each record is a column-name -> value map; associations are nested maps (belongs-to) or slices of maps (has-many).
type Predicate ¶
type Predicate struct {
// Name is the predicate suffix, e.g. "cont", "not_eq" or "gteq_any".
Name string
// WantsArray reports whether the predicate consumes a list of values
// (in/not_in and the _any/_all compounds).
WantsArray bool
// contains filtered or unexported fields
}
Predicate describes a Ransack search predicate, such as eq, cont or gteq. The exported fields let a Backend translate a condition to its own query language; Match evaluates the predicate in memory.
type Search ¶
Search is the parsed form of a Ransack "q" params hash: a tree of conditions (Root), an ordered list of sorts, a distinct flag and any parse errors. It is the value the Ruby-facing Model.ransack(q) returns; .result is obtained by handing the Search to a Backend.
func New ¶
New parses a params hash against ctx. A nil ctx is treated as an open context (every attribute allowed). Recognised structural keys are "m" (combinator), "g" (nested groups), "s"/"sorts" (ordering) and "distinct"/"d".
func (*Search) Apply ¶
Apply is the built-in, ORM-free evaluator: it filters records by the condition tree, orders them by the sorts and, when Distinct is set, removes duplicate rows.
