Class: ConvertSdk::RuleManager Private
- Inherits:
-
Object
- Object
- ConvertSdk::RuleManager
- Defined in:
- lib/convert_sdk/rule_manager.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
The audience/segmentation rule walk — OR -> AND -> OR_WHEN — ported EXACTLY
from the JS SDK packages/rules/src/rule-manager.ts. JS is the only truth
here; the PHP port is quarantined (it diverges on the existence operators and
on isIn case-folding — see Comparisons).
Structure & short-circuit order (mirrors rule-manager.ts:117-255):
* Top OR (+isRuleMatched+): for each AND-group, +match = process_and+;
return +true+ on the first matching group; after the loop return +match+
unless it is +false+ (so a {RuleError} sentinel propagates out). A missing
or empty +OR+ logs +RULE_NOT_VALID+ at warn and returns +false+.
* AND (+process_and+): for each OR_WHEN leaf-list, +match = process_or_when+;
return +match+ on the FIRST non-+true+ result (a +false+ or a sentinel
short-circuits the AND). All +true+ -> +true+. Missing/empty +AND+ ->
+RULE_NOT_VALID+ warn + +false+.
* OR_WHEN (+process_or_when+): for each leaf rule, +match = process_rule_item+;
return +true+ on the first match; after the loop return +match+ unless it
is +false+. Missing/empty +OR_WHEN+ -> +RULE_NOT_VALID+ warn + +false+.
FR22 safety invariant: EVERY empty/missing block shape returns false with a
RULE_NOT_VALID warn — an empty audience excludes everyone, it never matches
everyone.
The undefined-fallback (rule-manager.ts:323-333): when the data key for a leaf
is ABSENT and the operator is +exists+/+doesNotExist+, the operator is invoked
against Comparisons::UNDEFINED (JS undefined) so existence semantics hold
for absent keys. Ruby models key-absence with the Comparisons::UNDEFINED
marker because a plain nil means "present null value" (JS null), which is
a different existence outcome.
RuleError propagation: a leaf that returns a RuleError sentinel propagates it up the walk via the non-true / non-false short-circuits above (Story 2.11 maps the surfaced sentinel to the public return).
Pure in-memory (NFR1). Rule options (+keys_case_sensitive+, negation) come
from the injected Config, never inline. Valid-rule outcomes log at debug;
invalid/empty shapes log RULE_NOT_VALID at warn (rule-manager.ts levels).
Constant Summary collapse
- RULE_NOT_VALID =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The
RULE_NOT_VALIDmessage — byte-identical to the JS SDK dictionary (+packages/enums/src/dictionary.ts:12+: "Provided rule is not valid"). Logged at warn for every empty/missing/invalid block, the FR22 exclusion signal. "Provided rule is not valid"
Instance Method Summary collapse
-
#initialize(config:, comparisons: Comparisons, log_manager: nil) ⇒ RuleManager
constructor
private
Build a rule walker bound to a Config's rule options and a comparison processor.
-
#is_rule_matched(data, rule_set, log_entry = nil) ⇒ Boolean, Sentinel
private
Walk a rule set against a data hash.
Constructor Details
#initialize(config:, comparisons: Comparisons, log_manager: nil) ⇒ RuleManager
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Build a rule walker bound to a Config's rule options and a comparison processor.
57 58 59 60 61 |
# File 'lib/convert_sdk/rule_manager.rb', line 57 def initialize(config:, comparisons: Comparisons, log_manager: nil) @keys_case_sensitive = config.keys_case_sensitive @comparisons = comparisons @log_manager = log_manager end |
Instance Method Details
#is_rule_matched(data, rule_set, log_entry = nil) ⇒ Boolean, Sentinel
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Walk a rule set against a data hash. The top OR level.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/convert_sdk/rule_manager.rb', line 70 def is_rule_matched(data, rule_set, log_entry = nil) or_groups = nonempty_block(rule_set, "OR") unless or_groups warn_rule_not_valid("RuleManager#is_rule_matched", log_entry) return false end match = false or_groups.each do |and_group| match = process_and(data, and_group) return true if match == true log_outcome("RuleManager#is_rule_matched", match, log_entry) end return match if match != false false end |