Skip to content

Commit

Permalink
Support deserializing RealmValue from DBKey
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsenko committed Jul 30, 2024
1 parent 146805c commit a6a7dd1
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 12 deletions.
16 changes: 15 additions & 1 deletion packages/realm_dart/lib/src/handles/native/init.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -153,7 +154,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
Expand Down Expand Up @@ -188,3 +198,7 @@ DynamicLibrary initRealm() {

return _library = realmLibrary;
}

extension<T> on T {
U cast<U>() => this as U;
}
13 changes: 11 additions & 2 deletions packages/realm_dart/lib/src/realm_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -400,17 +401,25 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectBaseMarker {

/// @nodoc
static void registerFactory<T extends RealmObjectBase>(T Function() factory) {
// Register type as both (T).hashCode.toString() and T.name
TypePlus.add<T>();
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<T>(id: T.name);
}

// We register a factory for both the type itself, but also the nullable
// version of the type.
_factories.putIfAbsent(T, () => factory);
_factories.putIfAbsent(_typeOf<T?>(), () => factory);
}

/// @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();
Expand Down
1 change: 1 addition & 0 deletions packages/realm_dart/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 11 additions & 9 deletions packages/realm_dart/test/serialization_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,19 @@ void main() {
expect(fromEJson<RealmValue>(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<DBRef>(rv.toEJson()), isA<DBRef>().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<DBRef<String>>(rv.toEJson()), isA<DBRef<String>>().having((r) => r.id, '\$id', 'Christian Eriksen'));
expect((fromEJson<RealmValue>(rv.toEJson()).value as Player).name, p.name);
});
});

test('Decimal128', () {
Expand Down

0 comments on commit a6a7dd1

Please sign in to comment.