Expand a ransack_alias named in advanced-search params - #1731
Conversation
A simple key goes through Condition.extract, which resolves aliases
before the attributes are built. Advanced-search params name the
attribute directly (a: { '0' => { name: 'term' } }), so the alias
reached Attribute.new as-is, passed valid? by being allowlisted under
its own name, and bound a column that does not exist, while
attribute_select offered it as an option.
Condition#attributes= now expands the name through
Context#resolve_aliases first: an alias to one attribute is built
under that name, and an alias to a compound becomes one attribute per
segment, with the compound's combinator as the fallback when the
params carry no explicit one.
Closes #1728
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Combinator fallback currently mishandles invalid and mixed combinators.
Review effort: Balanced
Findings: 1
What changed in this PR
Expands ransack_alias values supplied through advanced-search parameters.
Changes:
- Resolves aliases before building condition attributes.
- Preserves alias-derived combinators unless explicitly overridden.
- Adds advanced-search alias coverage.
| File | Description |
|---|---|
lib/ransack/nodes/condition.rb |
Expands aliased attributes and derives combinators. |
spec/ransack/active_record/ransack_alias_spec.rb |
Tests advanced-search alias behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| # `name_or_email` ORs its two attributes without an `m` in the params. | ||
| def combinator | ||
| @attributes.size > 1 ? @combinator : nil | ||
| @attributes.size > 1 ? (@combinator || @alias_combinator) : nil |
There was a problem hiding this comment.
Good catch, fixed in 138cd40. Condition#combinator= now records whether a non-blank value was supplied, and the alias combinator is used only when none was. An unknown m still normalises to nil and fails valid_combinator?, so the condition is dropped (or raises Invalid combinator under ransack!) like any other multi-attribute condition. Spec added for both modes.
Node#combinator= normalises an unknown combinator such as `nand` to nil in a permissive search, so the alias fallback would have run the expanded condition with the alias's own combinator where any other multi-attribute condition is dropped by valid_combinator?. Track whether a non-blank combinator was supplied and use the fallback only for a missing or blank `m`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Note
This PR was opened by Claude (Claude Code), acting on behalf of @scarroll32.
Closes #1728.
Why
A
ransack_aliasworked in a simple key (term_cont=a) but not in advanced-search params (a: { '0' => { name: 'term' } }). The simple key goes throughCondition.extract, which resolves aliases before the attributes are built. The advanced params name the attribute directly, so the alias reachedAttribute.newas-is, passedvalid?by being allowlisted under its own name, and bound a column that does not exist.attribute_selectlistsransackable_attributes, which includes the alias, so any advanced-search form on a model with an alias offered a choice that 500'd (activerecord-hackery/ransack_demo#113).What
Condition#attributes=now expands each name throughContext#resolve_aliasesbefore building, the same lookup the simple path uses, so the two entry points agree:daddy→parent_name) is built under the target name.term→name_or_email) becomes one attribute per segment, joined by the compound's combinator.person_termonArticle) expands too, sinceresolve_aliasesalready handles that.min the params wins over the compound's combinator; a blankm, which a form may send after the attributes, does not wipe it.name.nil?bypass thatGrouping#new_conditionrelies on.attribute_selectis unchanged: it keeps offering the alias, and what it offers now works. The value reads back under the alias from its grouping (grouping.term_cont), as the existing#689behaviour already did for a single-attribute alias.Verification
ransack_alias_spec.rbunder "named in advanced-search params": compound alias, single association alias, alias on an associated model, blankmafter the attributes, explicitmwinning, alias mixed with a plain attribute, read-back from the grouping, andattribute_selectstill listing the alias🤖 Generated with Claude Code