activeagent 1.6.3 → 1.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/active_agent/schema_tools.rb +66 -0
- data/lib/active_agent/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0332669c4ffee1ccbea3e1645e126acac6b4e957b980000e5d96baedc908638
|
|
4
|
+
data.tar.gz: 1d6062b56a6e7fc0e76b965d308df706c3be563292344cdf68b500046e838784
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0a940227737d94497c19e8760cf1241ea02f6078987f8cd27f78b0b1a1fb22ac90c8b924dff87e85a4bf8f13c952f6a36eec388dd806f56d230f5b38c9fe59b
|
|
7
|
+
data.tar.gz: df01fdb757be0bcfa549086dfe0082db0ada892fc552600087d07fe9c1299a4aa4d4c897987cbda897832d11df50f19368261413647f63db4e636a4bb5bb98e5
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.6.4] - 2026-09-22
|
|
11
|
+
|
|
12
|
+
Releases `activeagent` and `actionagent` 1.6.4 from one tag. A patch on 1.6.3
|
|
13
|
+
carrying one fix to `SchemaTools`, for a filter that answered confidently and
|
|
14
|
+
wrongly instead of failing.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- A Rails enum is offered to the model as its names (`{type: "string", enum:
|
|
19
|
+
[...]}`) instead of the integer backing it. `SchemaGenerator` reads enums from
|
|
20
|
+
inclusion validators and never consulted `defined_enums`, so a `status` column
|
|
21
|
+
reached the model as a bare integer with no labels.
|
|
22
|
+
- A filter value outside an enum — alone or inside an IN list — is rejected,
|
|
23
|
+
naming the valid values, instead of matching no rows. `status: "pending"`
|
|
24
|
+
returned `{count: 0}`, which an agent reports as a fact, indistinguishable
|
|
25
|
+
from "none match". Same reasoning as the unknown-operator rejection in
|
|
26
|
+
`range_predicates!`.
|
|
27
|
+
- An enum is no longer offered the range form. Its integer backing is a
|
|
28
|
+
declaration-order artefact, so `status: {gt: 1}` was a meaningless filter that
|
|
29
|
+
still returned a confident count.
|
|
30
|
+
|
|
10
31
|
## [1.6.3] - 2026-09-18
|
|
11
32
|
|
|
12
33
|
Releases `activeagent` and `actionagent` 1.6.3 from one tag.
|
|
@@ -332,6 +332,8 @@ module ActiveAgent
|
|
|
332
332
|
"`#{key}` is not a filterable attribute. Allowed filters: #{filterable.join(", ")}"
|
|
333
333
|
end
|
|
334
334
|
|
|
335
|
+
validate_enum_value!(column, value)
|
|
336
|
+
|
|
335
337
|
memo[column] = value
|
|
336
338
|
end
|
|
337
339
|
|
|
@@ -386,6 +388,40 @@ module ActiveAgent
|
|
|
386
388
|
end
|
|
387
389
|
end
|
|
388
390
|
|
|
391
|
+
# A value outside a Rails enum reaches `where` as an unmatched name and
|
|
392
|
+
# returns zero rows — the same silent-nothing that {.range_predicates!}
|
|
393
|
+
# rejects for an unknown operator, and just as bad here: an agent reads
|
|
394
|
+
# "0 tickets under review" as a fact rather than a mistyped filter.
|
|
395
|
+
#
|
|
396
|
+
# The range form is not offered on an enum (see {.range_filterable?}), so
|
|
397
|
+
# a Hash here is a filter that cannot mean anything.
|
|
398
|
+
#
|
|
399
|
+
# @api private
|
|
400
|
+
# @raise [UnpermittedAttribute] on a value the enum does not define
|
|
401
|
+
def validate_enum_value!(column, value)
|
|
402
|
+
values = enum_values_for(column)
|
|
403
|
+
return if values.blank?
|
|
404
|
+
|
|
405
|
+
if value.is_a?(Hash)
|
|
406
|
+
raise UnpermittedAttribute,
|
|
407
|
+
"`#{column}` is an enum and cannot be compared as a range. " \
|
|
408
|
+
"Allowed values: #{values.keys.join(", ")}"
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
# An Array is an IN filter, which `where` silently narrows to its
|
|
412
|
+
# defined members just as it drops a lone undefined one.
|
|
413
|
+
Array(value).each do |member|
|
|
414
|
+
# The schema offers names only, so an integer here came from a
|
|
415
|
+
# model ignoring it. Accepted anyway: it is unambiguous, and a host
|
|
416
|
+
# calling the tool directly in Ruby reasonably passes the backing
|
|
417
|
+
# value.
|
|
418
|
+
next if values.key?(member.to_s) || values.value?(member)
|
|
419
|
+
|
|
420
|
+
raise UnpermittedAttribute,
|
|
421
|
+
"`#{member}` is not a valid `#{column}`. Allowed values: #{values.keys.join(", ")}"
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
389
425
|
# Projects a record down to the declared return columns.
|
|
390
426
|
#
|
|
391
427
|
# The projection happens in SQL (+select+) as well as here, but the Ruby
|
|
@@ -455,14 +491,44 @@ module ActiveAgent
|
|
|
455
491
|
properties = schema[:schema][:properties]
|
|
456
492
|
|
|
457
493
|
filterable.index_with do |column|
|
|
494
|
+
next enum_property(column) if enum_column?(column)
|
|
495
|
+
|
|
458
496
|
scalar = (properties[column] || { type: "string" }).deep_dup
|
|
459
497
|
range_filterable?(column) ? with_range_form(column, scalar) : scalar
|
|
460
498
|
end
|
|
461
499
|
end
|
|
462
500
|
|
|
501
|
+
# A Rails enum is declared on the model, not through the inclusion
|
|
502
|
+
# validator SchemaGenerator reads, so without this a `status` column
|
|
503
|
+
# reaches the model as a bare integer: no labels, no constraint. The
|
|
504
|
+
# names are the model's own API (`Ticket.open`, `status: "open"`), so
|
|
505
|
+
# they are what the tool offers.
|
|
506
|
+
#
|
|
507
|
+
# @api private
|
|
508
|
+
def enum_property(column)
|
|
509
|
+
{ type: "string", enum: enum_values_for(column).keys, description: "#{column.to_s.humanize} field" }
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
# @api private
|
|
513
|
+
def enum_column?(column)
|
|
514
|
+
enum_values_for(column).present?
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
# @api private
|
|
518
|
+
def enum_values_for(column)
|
|
519
|
+
@model.defined_enums[column.to_s] || {}
|
|
520
|
+
end
|
|
521
|
+
|
|
463
522
|
# Dates, times and numbers are the columns a question like "overdue" or
|
|
464
523
|
# "more than 10" actually needs a comparison on.
|
|
524
|
+
#
|
|
525
|
+
# An enum is backed by an integer but is not ordered in any sense a
|
|
526
|
+
# question can use: `status > 1` is an artefact of declaration order, so
|
|
527
|
+
# offering the range form on one invites a meaningless filter that still
|
|
528
|
+
# returns a confident count.
|
|
465
529
|
def range_filterable?(column)
|
|
530
|
+
return false if enum_column?(column)
|
|
531
|
+
|
|
466
532
|
RANGE_FILTERABLE_TYPES.include?(@model.type_for_attribute(column).type)
|
|
467
533
|
end
|
|
468
534
|
|
data/lib/active_agent/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activeagent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.6.
|
|
4
|
+
version: 1.6.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Bowen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-09-
|
|
11
|
+
date: 2026-09-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionpack
|