Skip to content

Commit

Permalink
Disallow embedded objects in RealmValue (capture in type system)
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsenko committed Dec 15, 2022
1 parent 8530dc7 commit 46bea2b
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
13 changes: 11 additions & 2 deletions common/lib/src/realm_types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ class Decimal128 {} // TODO Support decimal128 datatype https://github.com/realm
/// @nodoc
abstract class RealmObjectMarker {}

/// @nodoc
abstract class TopLevelObjectMarker implements RealmObjectMarker {}

/// @nodoc
abstract class EmbeddedObjectMarker implements RealmObjectMarker {}

/// @nodoc
abstract class AsymmetricObjectMarker implements RealmObjectMarker {}

/// A type that can represent any valid realm data type, except collections and embedded objects.
///
/// You can use [RealmValue] to declare fields on realm models, in which case it must be non-nullable,
Expand Down Expand Up @@ -148,7 +157,7 @@ class RealmValue {
const RealmValue.int(int i) : this._(i);
const RealmValue.double(double d) : this._(d);
// TODO: RealmObjectMarker introduced to avoid dependency inversion. It would be better if we could use RealmObject directly. https://github.com/realm/realm-dart/issues/701
const RealmValue.realmObject(RealmObjectMarker o) : this._(o);
const RealmValue.realmObject(TopLevelObjectMarker o) : this._(o);
const RealmValue.dateTime(DateTime timestamp) : this._(timestamp);
const RealmValue.objectId(ObjectId id) : this._(id);
// const RealmValue.decimal128(Decimal128 decimal) : this._(decimal); // not supported yet
Expand All @@ -162,7 +171,7 @@ class RealmValue {
o is int ||
o is Float ||
o is double ||
o is RealmObjectMarker ||
o is TopLevelObjectMarker ||
o is DateTime ||
o is ObjectId ||
// o is Decimal128 || // not supported yet
Expand Down
4 changes: 2 additions & 2 deletions lib/src/realm_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -432,10 +432,10 @@ mixin RealmObjectBase on RealmEntity implements RealmObjectMarker, Finalizable {
}

/// @nodoc
mixin RealmObject on RealmObjectBase {}
mixin RealmObject on RealmObjectBase implements TopLevelObjectMarker {}

/// @nodoc
mixin EmbeddedObject on RealmObjectBase {}
mixin EmbeddedObject on RealmObjectBase implements EmbeddedObjectMarker {}

extension EmbeddedObjectExtension on EmbeddedObject {
/// Retrieve the [parent] object of this embedded object.
Expand Down
11 changes: 10 additions & 1 deletion test/realm_value_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ import 'test.dart';

part 'realm_value_test.g.dart';

@RealmModel(ObjectType.embeddedObject)
class _TuckedIn {
int x = 42;
}

@RealmModel()
class _AnythingGoes {
@Indexed()
Expand All @@ -47,7 +52,7 @@ void main() {
Uuid.v4(),
];

final config = Configuration.inMemory([AnythingGoes.schema]);
final config = Configuration.inMemory([AnythingGoes.schema, TuckedIn.schema]);
final realm = getRealm(config);

for (final x in values) {
Expand All @@ -62,6 +67,10 @@ void main() {
expect(() => realm.write(() => realm.add(AnythingGoes(oneAny: RealmValue.from(<int>[1, 2])))), throwsArgumentError);
});

test('Embedded object not allowed in RealmValue', () {
expect(() => realm.write(() => realm.add(AnythingGoes(oneAny: RealmValue.from(TuckedIn())))), throwsArgumentError);
});

for (final x in values) {
test('Switch $x', () {
final something = AnythingGoes(oneAny: RealmValue.from(x));
Expand Down
39 changes: 39 additions & 0 deletions test/realm_value_test.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 46bea2b

Please sign in to comment.