Skip to content

Commit

Permalink
Add collection filtering support
Browse files Browse the repository at this point in the history
  • Loading branch information
Inobtenio committed May 26, 2020
1 parent c1de39b commit 68e1ad7
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/query.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
library query;

export 'package:json_api/src/query/fields.dart';
export 'package:json_api/src/query/filters.dart';

This comment has been minimized.

Copy link
@f3ath

f3ath May 29, 2020

Owner

@Inobtenio I like the idea of this change, would you like to open a PR?

This comment has been minimized.

Copy link
@Inobtenio

Inobtenio May 29, 2020

Author Contributor

I don't see why not. Any further improvements about this you could have in mind, @f3ath?

This comment has been minimized.

Copy link
@f3ath

f3ath May 29, 2020

Owner

Just nitpicking:

  • All other query helpers are named exactly as the corresponding parameters, so I'd prefer it to be Filter(singular) for consistency
  • The project files have EOL at the end of files.

Also, I'm planning to move this part out to a separate package in the future (also changing the API slightly). If you have time, you could add this logic there as well https://github.com/f3ath/json-api-common

This comment has been minimized.

Copy link
@Inobtenio

Inobtenio May 30, 2020

Author Contributor

Sounds good. Actually, Filter was the original name but I changed it since I encountered conflicts with other classes in my project. I wasn't planning for this to be public but yes, I better make it consistent.
I'll open a PR on json-api-common as well.

export 'package:json_api/src/query/include.dart';
export 'package:json_api/src/query/page.dart';
export 'package:json_api/src/query/query_parameters.dart';
Expand Down
30 changes: 30 additions & 0 deletions lib/src/query/filters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:json_api/src/query/query_parameters.dart';

/// Query parameters defining Filters
/// @see https://jsonapi.org/recommendations/#filtering
class Filters extends QueryParameters {
/// The [filter] argument maps the resource type to a list of filters.
///
/// Example:
/// ```dart
/// Filters({'articles': ['title', 'body'], 'people': ['name']}).addTo(url);
/// ```
/// encodes to
/// ```
/// ?filter[articles]=title,body&filter[people]=name
/// ```
Filters(Map<String, List<String>> filter)
: _filter = {...filter},
super(filter.map((k, v) => MapEntry('filter[$k]', v.join(','))));

/// Extracts the requested filter from the [uri].
static Filters fromUri(Uri uri) => Filters(uri.queryParameters
.map((k, v) => MapEntry(_regex.firstMatch(k)?.group(1), v.split(',')))
..removeWhere((k, v) => k == null));

List<String> operator [](String key) => _filter[key];

static final _regex = RegExp(r'^filter\[(.+)\]$');

final Map<String, List<String>> _filter;
}
23 changes: 23 additions & 0 deletions test/unit/query/filters_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import 'package:json_api/src/query/filters.dart';
import 'package:test/test.dart';

void main() {
test('Can decode url', () {
final uri = Uri.parse(
'/articles?include=author&filter%5Barticles%5D=title%2Cbody&filter%5Bpeople%5D=name');
final filter = Filters.fromUri(uri);
expect(filter['articles'], ['title', 'body']);
expect(filter['people'], ['name']);
});

test('Can add to uri', () {
final filter = Filters({
'articles': ['title', 'body'],
'people': ['name']
});
final uri = Uri.parse('/articles');

expect(filter.addToUri(uri).toString(),
'/articles?filter%5Barticles%5D=title%2Cbody&filter%5Bpeople%5D=name');
});
}

0 comments on commit 68e1ad7

Please sign in to comment.