Class: Karafka::Web::Ui::Lib::Filter
- Inherits:
-
Object
- Object
- Karafka::Web::Ui::Lib::Filter
- Defined in:
- lib/karafka/web/ui/lib/filter.rb
Overview
It handles filtering in place by mutating appropriate resources and sub-components, exactly like the [[Sorter]]. Because of that it must only be used on structures that are safe to mutate (per-request data), never on shared/live structures like the app routing.
Filtering engine for deep in-memory structures. It supports hashes, arrays and hash
proxies. It is a companion to the [[Sorter]] and follows the same wiring
(a per-controller allow-list plus an in-place call), but instead of reordering a
structure it removes the elements that do not match a keyword query.
Matching is a case-insensitive substring check performed against the allowed attributes
of each element (via public_send or hash lookup) and against hash keys (so structural
labels such as topic or consumer group names are searchable).
It uses match-propagation: a container (array/hash) is kept when it matches directly or when any of its descendants match. That way filtering a nested structure by a topic name keeps that topic with all of its children while dropping the branches that have nothing in common with the query.
Instance Method Summary collapse
-
#call(resource) ⇒ Hash, ...
Filters the structure in place and returns it.
-
#initialize(filter_query, allowed_attributes:, field: nil) ⇒ Filter
constructor
A new instance of Filter.
Constructor Details
#initialize(filter_query, allowed_attributes:, field: nil) ⇒ Filter
Returns a new instance of Filter.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/karafka/web/ui/lib/filter.rb', line 44 def initialize(filter_query, allowed_attributes:, field: nil) @query = filter_query.to_s.downcase.strip allowed = allowed_attributes.is_a?(Hash) ? allowed_attributes.keys : allowed_attributes # A declared field is either a plain attribute (matched on records) or a key alias # (matched on nested hash keys at a path). Key aliases are duck-typed: they respond to # `path` (a `KeyField`), which nothing else in the allow-list does. @allowed = [] @aliases = {} Array(allowed).each do |attribute| if attribute.respond_to?(:path) @aliases[attribute.name.to_s] = attribute.path else # Normalize to strings so symbol keys from controllers and the string field coming # from the request params compare cleanly @allowed << attribute.to_s end end field = field.to_s # When the selected field is a key alias, filtering prunes hash keys at its path instead # of matching record attributes if @aliases.key?(field) @alias_path = @aliases[field] else @alias_path = nil @field = @allowed.include?(field) ? field : nil end # Things we have already seen and filtered. Prevents crashing (and infinite loops) on # circular dependencies when the same resources are present in different parts of the # tree. We cache the match result so a second visit returns the same answer. @seen = {} end |
Instance Method Details
#call(resource) ⇒ Hash, ...
Filters the structure in place and returns it.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/karafka/web/ui/lib/filter.rb', line 87 def call(resource) # Skip if there is nothing to filter on return resource if @query.empty? # Skip if there are no criteria to match against. Just like the sorter ignores a # disallowed field, we do not want to prune anything with nothing to match on. return resource if @allowed.empty? && @aliases.empty? if @alias_path # Field scoped to a key alias: prune the hash keys at the alias path keep_by_key_alias!(resource, @alias_path) else keep?(resource, 0) end resource end |