Repository navigation
fix(agent): keep the search and segments of a select-all in delete, actions and dissociate [PRD-1667] - #414
Conversation
…ctions and dissociate [PRD-1667] A select-all request carries the list's search, segment and live-query segment in all_records_subset_query. Bulk delete, bulk actions and dissociate/delete-related built their filter from the condition tree, the ids and the scope only, so "Delete all" on a searched list deleted the whole collection. The three routes now build their filter through one QueryHandler#build_context_filter, as the Node agent does with ContextFilterFactory.build. parse_query_segment and parse_segment read the select-all body too. Refs: PRD-1667 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Coverage Impact ⬆️ Merging this pull request will increase total coverage on Modified Files with Diff Coverage (12) 🤖 Increase coverage with AI coding...🚦 See full report on Qlty Cloud » 🛟 Help
|
…ete matches [PRD-1667] The cleanup ran before the delete filter was built and from the request's ids, so a rejected filter still cleared references, and a select-all cleared those of the excluded records instead of the deleted ones. It now lists the records through the final filter first. A select-all body sending segment: false falls back to the query string segment again. Refs: PRD-1667 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hercemer42
left a comment
There was a problem hiding this comment.
Spec (PRD-1667): not met in every case. The ticket holds the gap.
…nswer the PRD-1667 review [PRD-1667] ActiveRecord chained every leaf onto the running query, so And[a, Or[x, y]] compiled as `a OR x OR y`: the search Or that select-all now carries into delete widened it to the whole collection, and already widened a searched list on main. Each branch is now built as its own relation, which ActiveRecord groups. build_context_filter checks the caller can read the fields its search and filter reach, and list, count and csv build through it too. Delete lists the polymorphic keys, deletes, then nullifies, so a failed delete leaves the children attached. Refs: PRD-1667 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 new issues
|
| condition_tree_segment | ||
| end | ||
|
|
||
| def build_context_filter(collection, args, permissions, caller, sort: nil) |
| relations = condition_tree.conditions.map { |condition| condition_relation(condition) } | ||
| return @collection.model.where(Arel.sql(aggregator == :or ? '1 = 0' : '1 = 1')) if relations.empty? | ||
|
|
||
| relations.reduce { |combined, relation| combined.send(aggregator, relation) } |
| length_func = Arel::Nodes::NamedFunction.new('LENGTH', [arel_attr]) | ||
| @query = query_aggregator(aggregator, @collection.model.where(length_func.gt(value))) | ||
| @collection.model.where(length_func.gt(value)) | ||
| end |
| selected_ids | ||
| ] | ||
| ) | ||
| filter = build_context_filter(context.child_collection, args, context.permissions, context.caller) |
There was a problem hiding this comment.
Claude Opus 5.5 (claude-opus-5-5), from manual testing at b9b6b40: a select-all delete on a searched related list now deletes fewer records than the user selected, because the related list itself ignores the search.
- Open a project's Tasks related list and search
brief. The list still shows every task,Fuel the rocketincluded. - Select all records, untick one, then Delete the tasks. The confirm says 3 tasks.
- Only the 2
brieftasks are deleted.Fuel the rocketsurvives.
Before this PR the same action deleted all 3, since the related list and the delete both ignored the search. Now the delete honours it through build_context_filter here, while list_related.rb:34, count_related.rb:28 and csv_related.rb:33 still build their filter from the scope and filters only, never search or segment. Node's related list, count and csv go through ContextFilterFactory.build.
A way out: build those three filters with build_context_filter, as list, count and csv now do.
There was a problem hiding this comment.
Claude Opus 5.5 (claude-opus-5-5): Related list, count and csv now build their filter through build_context_filter, so they show and count what a select-all delete reaches.
76957e2
Why
Each route has a spec where a search and a segment reach the related filter.
Related count also applies the list's filters now, which it used to drop.
…sv [PRD-1667] A select-all delete on a searched related list now honours the search, but the related list, count and csv still ignored it, so the list showed records the delete would not touch. The three routes now build their filter through build_context_filter, as Node does with ContextFilterFactory.build. Related count also applies the list's filters, which it used to drop. Refs: PRD-1667 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hercemer42
left a comment
There was a problem hiding this comment.
Approved after /verify-fixes run 414-20261020124244-hercemer42-verify: 6 findings of 414-20261016144136-hercemer42 closed or accepted, none reopened.
## [1.46.2](v1.46.1...v1.46.2) (2026-10-20) ### Bug Fixes * **agent:** keep the search and segments of a select-all in delete, actions and dissociate [PRD-1667] ([#414](#414)) ([8d4db0f](8d4db0f))
|
🎉 This PR is included in version 1.46.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |

Fixes PRD-1667: Delete all on a searched list deleted the whole collection.
What changes
QueryHandler#build_context_filter, the Ruby counterpart of Node'sContextFilterFactory.build, which also runsassert_can_read_query_fields.parse_query_segmentandparse_segmentalso readall_records_subset_query. A searched related list now shows only what a select-all delete on it reaches, and related count applies the list's filters too.And[a, Or[x, y]]compiled asa OR x OR y, so the searchOrwidened a searched Delete all to the whole collection (and already widened a searched, filtered list onmain). After: each branch is its own relation, which ActiveRecord groups. A failed delete also no longer leaves polymorphic children detached: the references are nullified after the delete succeeds.Decisions
Definition of Done
General
Security
Squash message
🤖 Generated with Claude Code
Note
Fix delete, actions and dissociate to keep search and segments of a select-all
build_context_filterhelper in query_handler.rb that combines the permission scope, request condition tree, and optional segment native-query condition tree, and carries search and segment metadata on the FilterQueryStringParser.parse_segmentandQueryHandler.parse_query_segmentresolve them with a fallback to the query-string segmentBadRequestErrorbefore deletion; polymorphic nullification is driven by a filteredlistwith an origin-key projection instead of raw selection IDsChanges since #414 opened
build_context_filter[b9b6b40]build_context_filterto accept sort and validate all query fields upfront [b9b6b40]Macroscope summarized 5640593.