Skip to content

Commit 0770973

Browse files
committed
feat: enhance filter options handling in request parameters
1 parent e1225e0 commit 0770973

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

src/main/kotlin/com/ctrlhub/core/router/request/RequestParameters.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.ctrlhub.core.router.request
22

33
data class FilterOption(
4-
val field: String,
4+
val field: String?,
55
val value: String
66
)
77

@@ -15,7 +15,17 @@ abstract class AbstractRequestParameters(
1515
offset?.let { queryParams["offset"] = it.toString() }
1616
limit?.let { queryParams["limit"] = it.toString() }
1717

18-
filterOptions.forEach { queryParams["filter"] = "${it.field}('${it.value}')" }
18+
filterOptions.forEach {
19+
// compute key once; if field is null use plain "filter", otherwise use "filter[field]"
20+
val key = it.field?.let { f -> "filter[$f]" } ?: "filter"
21+
val existing = queryParams[key]
22+
queryParams[key] = if (existing.isNullOrEmpty()) {
23+
it.value
24+
} else {
25+
// append multiple filter values with a comma
26+
"$existing,${it.value}"
27+
}
28+
}
1929

2030
return queryParams
2131
}
@@ -27,6 +37,7 @@ class RequestParameters(
2737
filterOptions: List<FilterOption> = emptyList()
2838
) : AbstractRequestParameters(offset, limit, filterOptions)
2939

40+
3041
open class RequestParametersWithIncludes<TIncludes>(
3142
offset: Int? = null,
3243
limit: Int? = null,
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.ctrlhub.core.router.request
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
import kotlin.test.assertNotNull
6+
7+
private enum class TestIncludes(private val v: String) : JsonApiIncludes {
8+
AUTHOR("author"), FORM("form");
9+
override fun value() = v
10+
}
11+
12+
class RequestParametersTest {
13+
14+
@Test
15+
fun `toMap includes offset and limit`() {
16+
val request = RequestParameters(offset = 5, limit = 25)
17+
val map = request.toMap()
18+
19+
assertEquals("5", map["offset"])
20+
assertEquals("25", map["limit"])
21+
}
22+
23+
@Test
24+
fun `single filter option produces filter key`() {
25+
val request = RequestParameters(
26+
filterOptions = listOf(FilterOption("status", "open"))
27+
)
28+
29+
val map = request.toMap()
30+
assertEquals("open", map["filter[status]"])
31+
}
32+
33+
@Test
34+
fun `multiple filter options for same field are appended with comma`() {
35+
val request = RequestParameters(
36+
filterOptions = listOf(
37+
FilterOption("status", "open"),
38+
FilterOption("status", "closed"),
39+
)
40+
)
41+
42+
val map = request.toMap()
43+
assertEquals("open,closed", map["filter[status]"])
44+
}
45+
46+
@Test
47+
fun `anonymous filter options append to filter key`() {
48+
val request = RequestParameters(
49+
filterOptions = listOf(
50+
FilterOption(null, "a"),
51+
FilterOption(null, "b")
52+
)
53+
)
54+
55+
val map = request.toMap()
56+
assertEquals("a,b", map["filter"])
57+
}
58+
59+
@Test
60+
fun `includes are serialized when using RequestParametersWithIncludes`() {
61+
val request = RequestParametersWithIncludes<TestIncludes>(
62+
includes = listOf(TestIncludes.AUTHOR, TestIncludes.FORM)
63+
)
64+
65+
val map = request.toMap()
66+
assertNotNull(map["include"]) // something present
67+
assertEquals("author,form", map["include"])
68+
}
69+
}

0 commit comments

Comments
 (0)