realm / realm-dart

Realm is a mobile database: a replacement for SQLite & ORMs.
Apache License 2.0
769 stars 87 forks source link

How to combine Freezed with Realm #1163

Open tbm98 opened 1 year ago

tbm98 commented 1 year ago

Problem

I want to combine Freezed with Realm to have able to compare object

Solution

Combine Freezed with Realm

Alternatives

Realm implement itself == operator

How important is this improvement for you?

Dealbreaker

Feature would mainly be used with

Local Database only

nielsenko commented 1 year ago

@tbm98 Thank you for taking an interest in our new SDK.

I'm afraid freezed and realm does not mingle well.

I notice you mark this as a deal-breaker for you, but before abandoning us, could you perhaps check out the freeze methods exposed on Realm, RealmList, RealmResults and any realm object. This is an easy and efficient way (constant time) of making the entire object graph reachable from a realm entity immutable. Perhaps this can serve the same benefit to you?

thigothoi commented 1 year ago

Hi @nielsenko. Currently, I am using a Database class to manage queries based on id. I would love to use ReamObject in cases like update data. But ReamObject doesn't support comparing two objects so I can't use it as the state of the application, because they can't tell when the value actually changed, which makes the app rebuild right away. even if the state remains unchanged. to solve that problem i currently have to create a mapping from RealmObject class using Freezed to be able to do that. But because there must be such a mapping class, it is not possible to keep the original RealmObject object, and I have to update data based on id (by querying RealmObject by id and using that object to update data).

So if RealmObject supports override hashCode, == operator then it will be very useful.

nielsenko commented 1 year ago

I have been discussing this with various stake holders today.

Today if you do the following, the last assert will fail:

import 'package:realm_dart/realm.dart';

part 'changed.g.dart';

@RealmModel()
class _Stuff {
  late String name;
}

void main(List<String> arguments) {
  final realm = Realm(Configuration.inMemory([Stuff.schema]));

  final x = Stuff('x');
  final y = Stuff('y');
  realm.write(() => realm.addAll([x, y]));

  final x1 = x.freeze();
  final y1 = y.freeze();

  // Change x
  realm.write(() => x.name = 'z');

  final x2 = x.freeze();
  final y2 = y.freeze();

  assert(x1 != x2);
  assert(y1 == y2); // <-- FAILS

  Realm.shutdown();
}

The reason is that equality in realm is based on the key of the object and the version it belongs to. Though the key is identical for y1 and y2 the version they stem from differs.

This is a very strict definition of equality and one that realm can calculate very efficiently.

In your case you want something less strict I guess?

Since most other SDKs allow for equality to be overriden, we are very likely to add a similar capability to Flutter / Dart, but I cannot make any promises yet - especially as to when.

Once/if we do be aware that doing the usual stuff, ie. comparing each property and do combine with&& will be much more expensive than the current approach.

One question though.. it is not immediately clear to me why you don't just listen for changes from the realm object using the changes stream? Perhaps you can elaborate.