Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RDART-969: Keypath filtering on collections #1714

Merged
merged 18 commits into from
Jun 14, 2024
Merged

Conversation

papafe
Copy link
Contributor

@papafe papafe commented Jun 7, 2024

This PR adds support for keypath filtering on collections

TODO:

  • Add support for lists
  • Add support for sets
  • Add support for dictionaries
  • Add basic tests for lists, sets, dictionaries (bulk of the tests will be on results). This includes verifying we can't use keypath filtering on collections that do not contain realm objects
  • Changelog

@papafe papafe requested a review from nielsenko June 11, 2024 09:45
@papafe
Copy link
Contributor Author

papafe commented Jun 11, 2024

@nielsenko
I've put the bulk of the tests for the keypath filtering on results, and I've left some basic tests for the other collections (lists, sets, dictionaries), so we don't repeat the same tests.
I have left some todos around about things I am not sure / we need to discuss, but functionally everything should work.

Copy link

coveralls-official bot commented Jun 12, 2024

Pull Request Test Coverage Report for Build 9477711446

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 87 of 90 (96.67%) changed or added relevant lines in 9 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 86.962%

Changes Missing Coverage Covered Lines Changed/Added Lines %
packages/realm_dart/lib/src/list.dart 12 13 92.31%
packages/realm_dart/lib/src/map.dart 13 14 92.86%
packages/realm_dart/lib/src/set.dart 12 13 92.31%
Totals Coverage Status
Change from base Build 9416962455: 0.2%
Covered Lines: 5996
Relevant Lines: 6895

💛 - Coveralls

@papafe papafe marked this pull request as ready for review June 12, 2024 12:21
Copy link
Contributor

@nielsenko nielsenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look mostly good to me. Most of my comments are more suggestions, but the the one about import 'dart:ffi'; is a blocker 😄

CHANGELOG.md Outdated
Comment on lines 55 to 54
PR [#1713](https://github.com/realm/realm-dart/pull/1713)). This does **not** imply that realm works on web!
for web without breaking compilation. (Issue [#1374](https://github.com/realm/realm-dart/issues/1374))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, sorry, I messed up the conflict it seems 🤦

CHANGELOG.md Outdated Show resolved Hide resolved
/// Allows listening for changes when the contents of this collection changes.
Stream<RealmListChanges<T>> get changes;

/// Allows listening for changes when the contents of this collection changes on one of the provided [keyPaths].
Stream<RealmListChanges<T>> changesFor([List<String>? keyPaths]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably a little late in the game... but since changesFor only makes sense for collections of realm objects we could make it an extension method like:

extension ListOfRealmObjectsEx<T extends RealmObject> extends RealmList<T> {
  Stream<RealmListChanges<T>> changesFor([List<String>? keyPaths]);
}

That way it becomes a compile error to try to call changesFor on RealmList<int> etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would actually make sense.
The only "issue" I see is that now changes is defined as changesFor(null) to avoid repetitions.
If we move changesFor to an extension method then we'd need to have some duplication (admittedly not a biggie though). It also seems Dart does not have protected methods, so I don't know if I can go around this with some other language constructs. Any suggestion?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could make a private _changesFor that both the changesFor extension method, and changes member delegates to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking something like that. In my mind it sounded uglier than it would probably be, I'll give it a try 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done it in the last commit

@@ -33,6 +33,9 @@ abstract class RealmMap<T extends Object?> with RealmEntity implements MapBase<S

/// Allows listening for changes when the contents of this collection changes.
Stream<RealmMapChanges<T>> get changes;

/// Allows listening for changes when the contents of this collection changes on one of the provided [keyPaths].
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we spend some time explaining the difference between null and []?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added more explanation on the extension method

packages/realm_dart/lib/src/map.dart Outdated Show resolved Hide resolved
packages/realm_dart/lib/src/results.dart Outdated Show resolved Hide resolved
@papafe
Copy link
Contributor Author

papafe commented Jun 14, 2024

@nielsenko I think I've addressed all the comments.
A couple of other things I've noticed, and that we don't necessarily need to address here, but I thought it would be worth writing down.

We have some inconsistencies with naming:

  1. In the errors for unmanaged sets we call them RealmSets, while we call lists just Lists (same for maps)
  2. Regarding notification controllers, we have ListNotificationController but RealmSetNotificationController.
  3. Regarding tests, we have list_test but we have realm_set_test/realm_map_test
  4. Maybe we should have a different suffix between the native handle implementation and the interface files. just having a look is a little bit confusing sometimes.

Some other considerations (that probably require some work):

  1. Maybe we can move the keypath property to the base NotificationController, instead of having it defined in the various specific classes
  2. Maybe we can have a base class for all collections (results, lists, sets, maps). This way we could move changes and some other common things there. The collection handle themselves could have a common base class.

@nielsenko
Copy link
Contributor

In my opinion..

  1. In the errors for unmanaged sets we call them RealmSets, while we call lists just Lists (same for maps)

Going forward we should try to reduce the use of realm prefix to where it is needed. This means only on public facing classes, that are likely to collide with other class names (RealmSet, RealmList, RealmMap, etc.). Internally we should avoid unless it makes code more readable.

  1. Regarding notification controllers, we have ListNotificationController but RealmSetNotificationController.

It should just be SetNotificationController.

  1. Regarding tests, we have list_test but we have realm_set_test/realm_map_test

it should just be set_test.dart.

  1. Maybe we should have a different suffix between the native handle implementation and the interface files. just having a look is a little bit confusing sometimes.

I'm a bit reluctant on this. For each handle, there is the interface, and two implementations.. I would prefer not to suffix the implementations with Native and Web (or whatever)

Some other considerations (that probably require some work):

  1. Maybe we can move the keypath property to the base NotificationController, instead of having it defined in the various specific classes
  1. Maybe we can have a base class for all collections (results, lists, sets, maps). This way we could move changes and some other common things there. The collection handle themselves could have a common base class.

The current C-api don't really give us much benefit, but yes.

However, let us land this PR as is, and get started on the weekend 😄 .. we can always address this later.

@nielsenko nielsenko self-requested a review June 14, 2024 13:04
Copy link
Contributor

@nielsenko nielsenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great work 👍

@papafe
Copy link
Contributor Author

papafe commented Jun 14, 2024

I'll merge this as soon as the CI agrees

@papafe papafe merged commit 16f34e5 into main Jun 14, 2024
53 of 56 checks passed
@papafe papafe deleted the fp/collection-keypath-new branch June 14, 2024 13:31
nirinchev added a commit that referenced this pull request Jun 18, 2024
* main:
  RDART-969: Keypath filtering on collections (#1714)
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 14, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants