diff --git a/packages/realm_dart/lib/src/handles/native/init.dart b/packages/realm_dart/lib/src/handles/native/init.dart index 375cbe253..2dec585cf 100644 --- a/packages/realm_dart/lib/src/handles/native/init.dart +++ b/packages/realm_dart/lib/src/handles/native/init.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:ejson/ejson.dart'; import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; +import 'package:type_plus/type_plus.dart'; import '../../cli/common/target_os_type.dart'; import '../../cli/metrics/metrics_command.dart'; @@ -156,7 +157,16 @@ EJsonValue encodeRealmValue(RealmValue value) { return toEJson(v); } -RealmValue decodeRealmValue(EJsonValue ejson) => RealmValue.from(fromEJson(ejson, allowCustom: false)); +RealmValue decodeRealmValue(EJsonValue ejson) { + Object? decoded = fromEJson(ejson, allowCustom: false); + if (decoded is DBRef) { + final t = TypePlus.fromId(decoded.collection); + final o = RealmObjectBase.createObject(t, null); + o.dynamic.set(o.objectSchema.primaryKey!.name, decoded.id); + return RealmValue.realmObject(o.cast()); + } + return RealmValue.from(decoded); +} /// @nodoc // Initializes Realm library @@ -191,3 +201,7 @@ DynamicLibrary initRealm() { return _library = realmLibrary; } + +extension on T { + U cast() => this as U; +} diff --git a/packages/realm_dart/lib/src/realm_object.dart b/packages/realm_dart/lib/src/realm_object.dart index fc17fe799..101cd88b7 100644 --- a/packages/realm_dart/lib/src/realm_object.dart +++ b/packages/realm_dart/lib/src/realm_object.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; import 'package:realm_common/realm_common.dart'; +import 'package:type_plus/type_plus.dart'; import 'configuration.dart'; import 'handles/handle_base.dart'; @@ -400,6 +401,14 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker { /// @nodoc static void registerFactory(T Function() factory) { + // Register type as both (T).hashCode.toString() and T.name + TypePlus.add(); + if (TypePlus.fromId(T.name) == UnresolvedType) { + // Only register by name, if no other class with the same name is registered + // Can happen, if the same class name is used in different libraries. + TypePlus.add(id: T.name); + } + // We register a factory for both the type itself, but also the nullable // version of the type. _factories.putIfAbsent(T, () => factory); @@ -407,10 +416,10 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker { } /// @nodoc - static RealmObjectBase createObject(Type type, RealmObjectMetadata metadata) { + static RealmObjectBase createObject(Type type, RealmObjectMetadata? metadata) { final factory = _factories[type]; if (factory == null) { - if (type == RealmObjectBase) { + if (type == RealmObjectBase && metadata != null) { switch (metadata.schema.baseType) { case ObjectType.realmObject: return _ConcreteRealmObject(); diff --git a/packages/realm_dart/pubspec.yaml b/packages/realm_dart/pubspec.yaml index 960c6096d..f557a2491 100644 --- a/packages/realm_dart/pubspec.yaml +++ b/packages/realm_dart/pubspec.yaml @@ -31,6 +31,7 @@ dependencies: cancellation_token: ^2.0.0 decimal: ^3.0.1 rational: ^2.2.3 + type_plus: ^2.1.1 dev_dependencies: build_cli: ^2.2.2 diff --git a/packages/realm_dart/test/serialization_test.dart b/packages/realm_dart/test/serialization_test.dart index 1bf93f9c5..f3f5a48a1 100644 --- a/packages/realm_dart/test/serialization_test.dart +++ b/packages/realm_dart/test/serialization_test.dart @@ -49,17 +49,19 @@ void main() { expect(fromEJson(r.toEJson()), r); } }); + } - test('RealmValue with RealmObject', () { - // load custom codecs for Player and Game. This is done to test that it - // doesn't interfere with the RealmValue codecs. - Realm(Configuration.inMemory([Player.schema, Game.schema])); + test('RealmObject', () { + // load custom codecs for Player and Game. This is done to test that it + // doesn't interfere with the RealmValue codecs. + Realm(Configuration.inMemory([Player.schema, Game.schema])); - final rv = RealmValue.from(Player('Christian Eriksen')); - expect(rv.toEJson(), {'\$id': 'Christian Eriksen', '\$ref': 'Player'}); - expect(fromEJson(rv.toEJson()), isA().having((r) => r.id, '\$id', 'Christian Eriksen')); - }); - } + final p = Player('Christian Eriksen'); + final rv = RealmValue.from(p); + expect(rv.toEJson(), {'\$id': 'Christian Eriksen', '\$ref': 'Player'}); + expect(fromEJson>(rv.toEJson()), isA>().having((r) => r.id, '\$id', 'Christian Eriksen')); + expect((fromEJson(rv.toEJson()).value as Player).name, p.name); + }); }); test('Decimal128', () {