Class: Woods::Console::ScopePredicateParser
- Inherits:
-
Object
- Object
- Woods::Console::ScopePredicateParser
- Defined in:
- lib/woods/console/scope_predicate_parser.rb
Overview
Parses Ransack-style predicate suffixes in scope hashes and builds safe Arel predicates without string interpolation.
Supported suffixes:
_eq, _not_eq — equality / inequality
_gt, _gteq, _lt, _lteq — numeric/date comparisons
_in, _not_in — set membership (value must be Array)
_null, _not_null — IS NULL / IS NOT NULL (value must be boolean)
_present — IS NOT NULL AND != '' (value must be boolean)
_blank — IS NULL OR = '' (value must be boolean)
_matches — LIKE pattern
Plain hash keys (no recognised suffix) are treated as equality conditions and handled by the standard ActiveRecord where(hash) path.
Every column reference is validated through ModelValidator#validate_column! before an Arel node is built — SQL injection via column names is impossible.
Constant Summary collapse
- SUPPORTED_SUFFIXES =
%w[ _eq _not_eq _gt _gteq _lt _lteq _in _not_in _null _not_null _present _blank _matches ].freeze
- SUFFIX_PATTERN =
Suffix pattern — longest suffix match wins because we scan the full list.
/(_eq|_not_eq|_gteq|_lteq|_gt|_lt|_not_in|_not_null|_in|_null|_present|_blank|_matches)\z/- SUFFIX_HINT =
"Supported suffixes: #{SUPPORTED_SUFFIXES.join(', ')}.".freeze
Instance Method Summary collapse
-
#initialize(model_name:, model_validator:) ⇒ ScopePredicateParser
constructor
A new instance of ScopePredicateParser.
-
#parse(relation, scope_hash) ⇒ ActiveRecord::Relation
Parse a scope hash and return an ActiveRecord::Relation.
Constructor Details
#initialize(model_name:, model_validator:) ⇒ ScopePredicateParser
Returns a new instance of ScopePredicateParser.
46 47 48 49 |
# File 'lib/woods/console/scope_predicate_parser.rb', line 46 def initialize(model_name:, model_validator:) @model_name = model_name @model_validator = model_validator end |
Instance Method Details
#parse(relation, scope_hash) ⇒ ActiveRecord::Relation
Parse a scope hash and return an ActiveRecord::Relation.
Keys without a recognised suffix are collected into a plain equality hash and applied via relation.where(hash) — the fast path. Keys with a recognised suffix are validated and built via Arel.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/woods/console/scope_predicate_parser.rb', line 61 def parse(relation, scope_hash) equality = {} arel_nodes = [] scope_hash.each do |raw_key, value| key = raw_key.to_s match = SUFFIX_PATTERN.match(key) if match suffix = match[1] column = key.delete_suffix(suffix) @model_validator.validate_column!(@model_name, column) arel_nodes << build_node(relation, column, suffix, value) else equality[raw_key] = value end end relation = relation.where(equality) if equality.any? arel_nodes.each { |node| relation = relation.where(node) } relation end |