Fix low-level c: API silently dropping conditions with Array envelope hashes (#1150)#1675
Open
ryoya1122 wants to merge 1 commit into
Conversation
…ys of envelope hashes (activerecord-hackery#1150) The low-level conditions API accepts `a:` (attributes) and `v:` (values) in two equivalent forms: * Hash form: `a: {'0' => {name: 'foo'}}`, `v: {'0' => {value: 'bar'}}` * Array form: `a: ['foo']`, `v: ['bar']` `Condition#attributes=` and `#values=` handled both shapes for the canonical Array form (plain names / values), but when an Array contained the same envelope hash that the Hash form unwraps, the parser did the wrong thing: * `a: [{name: 'foo'}]` -> the entire `{name: 'foo'}` Hash became the attribute name, the attribute failed validation, and the condition was silently dropped (producing a query with no WHERE clause). * `v: [{value: 'bar'}]` -> the entire `{value: 'bar'}` Hash became the value, ending up stringified inside the SQL (`LIKE '%{"value" => "bar"}%'`). The Array branches now detect envelope hashes (`{name: ...}` / `{value: ...}`) and extract the same fields the Hash branches do, while still passing plain names / values through unchanged.
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.
Closes #1150.
Problem
The low-level conditions API (
c: [{a:, v:, p:}]) acceptsa:(attributes) andv:(values) in two equivalent forms:a: {'0' => {name: 'foo'}},v: {'0' => {value: 'bar'}}a: ['foo'],v: ['bar']However when the Array form contained the same envelope hash that the Hash form unwraps, the parser did the wrong thing.
Bug 1 —
a:Array of{name: ...}envelopes silently drops the condition:Bug 2 —
v:Array of{value: ...}envelopes leaks the whole hash into the SQL:The Hash form of both
a:andv:worked correctly, so the asymmetry was the bug.Cause
Condition#attributes=and#values=switch onArray/Hash. The Hash branches unwrap each entry's:name/:value, but the Array branches assumed every element was a plain name or plain value. When an envelope hash was supplied, it was passed straight through:attributes=Array branch:Attribute.new(@context, {name: 'name'}, [])was built, failedvalid?, and was dropped.values=Array branch:Value.new(@context, {value: 'Kasper'})was built, which later renders the hash viato_sinside the SQL.Fix
In the Array branch of each setter, detect envelope hashes (with
:nameor:valuekeys, either symbol or string) and extract the same fields the Hash branch already does. Plain Array elements (the canonicala: ['name'],v: ['Ernie']form used throughout existing specs) continue to work unchanged.Compatibility
The Array branches keep the existing behavior for every shape except the two envelope forms documented as broken in #1150:
a:/v:element shape"foo"(plain name / value){name: ...}/{value: ...}{"name" => ...}(string key){name:, ransacker_args:}{other_key: ...}(no envelope)nilThe envelope-detection check is intentionally narrow (
Hashand has a:name/:valuekey) so that arbitrary Hash values — e.g. searches against a JSON column where the value itself is a Hash — keep flowing through Arel unchanged.CI is green on the full matrix (SQLite / PostgreSQL / PostGIS / MySQL × Rails 7.2-stable / 8.0-stable × Ruby 3.1.4 / 3.2.2).
Tests
Three new specs under
Ransack::Search#build > low-level c: API with Array of envelope hashesinspec/ransack/search_spec.rb::namefrom each attribute hash inside an Array (red before, green after):valuefrom each value hash inside an Array (red before, green after)Full suite:
515 examples, 0 failures, 1 pendingonv5.0.0+ this branch (SQLite, ActiveRecord 7.2.3.1, Ruby 3.4.9).Targets
v5.0.0per #1640.