Add Include, Exclude, In, and NotIn membership expressions#1028
Open
jnunemaker wants to merge 2 commits into
Open
Add Include, Exclude, In, and NotIn membership expressions#1028jnunemaker wants to merge 2 commits into
jnunemaker wants to merge 2 commits into
Conversation
Include(left, right) returns true when left is an array that contains right, or when left is a string that contains right as a substring. Anything else (nil, hashes, numbers, string/non-string mixes) evaluates to false rather than duck-typing include?, so behavior doesn't silently vary with property type. Also make unknown expression names fail closed instead of crashing: Expression.build now raises Flipper::Expression::UnknownExpression (a NameError subclass with the same message, so existing rescues keep working) and the expression gate rescues it, warns, and returns false. Older gems that sync expression data written by newer versions will treat the feature as disabled instead of raising NameError out of Flipper.enabled? on every check. const_get now passes inherit: false so expression names can't resolve to top-level constants like ::Kernel. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Complete the membership operator surface around Include with its negation and the "is one of a static list" checks users expect from other flag systems: - Exclude(left, right) is the negation of Include (collection/string does not contain the value). A missing property, hash, or number "excludes" the value, mirroring how NotEqual treats a missing property. - In(value, list) is true when list is an array containing value (SQL IN / "is one of"): the property on the left, a static array on the right. - NotIn(value, list) is the negation of In. Both are strict about the right side being an Array so no substring matching leaks in from Include, and a non-array right fails closed to false rather than duck-typing include?. To support static lists, Expression.build now accepts array literals: they become a single Constant holding the built element values, so elements are normalized the same way scalar constants are (Symbol => String). Previously arrays raised ArgumentError and list membership was inexpressible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a full set of membership operators to the expression DSL:
Include/Excludecheck whether an array or string property contains a value (strings match substrings), andIn/NotIncheck whether a property value is one of a static list (SQLIN/ "is one of"), with the property on the left and a static array on the right. All four fail closed rather than duck-typinginclude?— non-array/string operands and type mismatches evaluate tofalseinstead of silently varying by property type — andExpression.buildnow accepts array literals so static lists are expressible. Unknown expression names now fail closed too:Expression.buildraisesFlipper::Expression::UnknownExpression(aNameErrorsubclass, so existing rescues keep working) and the expression gate rescues it, warns, and treats the feature as disabled, so older gems reading newer expression data no longer crashFlipper.enabled?;const_getalso passesinherit: falseso expression names can't resolve to top-level constants like::Kernel. Reference docs for the new operators still need to be added to the cloud docs site.🤖 Generated with Claude Code