Add support for accessing linking objects / backlinks (#1101)
* Add support for linkingObjects * Test linkingObjects * Borrow names helper from list tests * include computed properties when serializing the schema for the RN debugger * add API docs * review comments * Expose admin users to JS (#1100) The JS binding used to conflate `SyncUser::is_admin()` with the user being created by calling `Realm.Sync.User.adminToken()`, but now that we expose a user’s role on the server under `is_admin()` this supposition is no longer correct. #1097 attempted to fix one such case, but fixing it only uncovered another: in `UserClass<T>::all_users()`. I’ve gone through all the callsites of `SyncUser::is_admin()` to make sure they don’t assume an admin token user. * [1.8.3] Bump version * add linkingObjects method to Realm.Object * changelog
This commit is contained in:
parent
f1695f33db
commit
9e0a9a3bd3
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,3 +1,14 @@
|
|||
vNext Release notes (TBD)
|
||||
=============================================================
|
||||
### Breaking changes
|
||||
* None
|
||||
|
||||
### Enhancements
|
||||
* Add support for Linking Objects (AKA Backlinks).
|
||||
|
||||
### Bug fixes
|
||||
* Node
|
||||
|
||||
1.8.3 Release notes (2017-6-27)
|
||||
=============================================================
|
||||
### Breaking changes
|
||||
|
|
|
@ -36,4 +36,14 @@ class Object {
|
|||
* @since 1.8.1
|
||||
*/
|
||||
objectSchema() {}
|
||||
|
||||
/**
|
||||
* Returns all the objects that link to this object in the specified relationship.
|
||||
* @param {string} objectType - The type of the objects that link to this object's type.
|
||||
* @param {string} property - The name of the property that references objects of this object's type.
|
||||
* @throws {Error} If the relationship is not valid.
|
||||
* @returns {Realm.Results} the objects that link to this object.
|
||||
* @since 1.9.0
|
||||
*/
|
||||
linkingObjects(objectType, property) {}
|
||||
}
|
||||
|
|
|
@ -241,8 +241,10 @@ Realm.defaultPath;
|
|||
* @typedef Realm~ObjectSchemaProperty
|
||||
* @type {Object}
|
||||
* @property {Realm~PropertyType} type - The type of this property.
|
||||
* @property {string} [objectType] - **Required** when `type` is `"list"`, and must match the
|
||||
* type of an object in the same schema.
|
||||
* @property {string} [objectType] - **Required** when `type` is `"list"` or `"linkingObjects"`,
|
||||
* and must match the type of an object in the same schema.
|
||||
* @property {string} [property] - **Required** when `type` is `"linkingObjects"`, and must match
|
||||
* the name of a property on the type specified in `objectType` that links to the type this property belongs to.
|
||||
* @property {any} [default] - The default value for this property on creation when not
|
||||
* otherwise specified.
|
||||
* @property {boolean} [optional] - Signals if this property may be assigned `null` or `undefined`.
|
||||
|
@ -262,7 +264,7 @@ Realm.defaultPath;
|
|||
* A property type may be specified as one of the standard builtin types, or as an object type
|
||||
* inside the same schema.
|
||||
* @typedef Realm~PropertyType
|
||||
* @type {("bool"|"int"|"float"|"double"|"string"|"date"|"data"|"list"|"<ObjectType>")}
|
||||
* @type {("bool"|"int"|"float"|"double"|"string"|"date"|"data"|"list"|"linkingObjects"|"<ObjectType>")}
|
||||
* @property {boolean} "bool" - Property value may either be `true` or `false`.
|
||||
* @property {number} "int" - Property may be assigned any number, but will be stored as a
|
||||
* round integer, meaning anything after the decimal will be truncated.
|
||||
|
@ -278,6 +280,9 @@ Realm.defaultPath;
|
|||
* @property {Realm.List} "list" - Property may be assigned any ordered collection
|
||||
* (e.g. `Array`, {@link Realm.List}, {@link Realm.Results}) of objects all matching the
|
||||
* `objectType` specified in the {@link Realm~ObjectSchemaProperty ObjectSchemaProperty}.
|
||||
* @property {Realm.Results} "linkingObjects" - Property is read-only and always returns a {@link Realm.Results}
|
||||
* of all the objects matching the `objectType` that are linking to the current object
|
||||
* through the `property` relationship specified in {@link Realm~ObjectSchemaProperty ObjectSchemaProperty}.
|
||||
* @property {Realm.Object} "<ObjectType>" - A string that matches the `name` of an object in the
|
||||
* same schema (see {@link Realm~ObjectSchema ObjectSchema}) – this property may be assigned
|
||||
* any object of this type from inside the same Realm, and will always be _optional_
|
||||
|
|
|
@ -30,7 +30,8 @@ export default class RealmObject {
|
|||
// Non-mutating methods:
|
||||
createMethods(RealmObject.prototype, objectTypes.OBJECT, [
|
||||
'isValid',
|
||||
'objectSchema'
|
||||
'objectSchema',
|
||||
'linkingObjects'
|
||||
]);
|
||||
|
||||
export function clearRegisteredConstructors() {
|
||||
|
|
|
@ -24,7 +24,7 @@ declare namespace Realm {
|
|||
* PropertyType
|
||||
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.html#~PropertyType }
|
||||
*/
|
||||
type PropertyType = string | 'bool' | 'int' | 'float' | 'double' | 'string' | 'data' | 'date' | 'list';
|
||||
type PropertyType = string | 'bool' | 'int' | 'float' | 'double' | 'string' | 'data' | 'date' | 'list' | 'linkingObjects';
|
||||
|
||||
/**
|
||||
* ObjectSchemaProperty
|
||||
|
@ -33,6 +33,7 @@ declare namespace Realm {
|
|||
interface ObjectSchemaProperty {
|
||||
type: PropertyType;
|
||||
objectType?: string;
|
||||
property?: string;
|
||||
default?: any;
|
||||
optional?: boolean;
|
||||
indexed?: boolean;
|
||||
|
@ -102,6 +103,11 @@ declare namespace Realm {
|
|||
* @returns ObjectSchema
|
||||
*/
|
||||
objectSchema(): ObjectSchema;
|
||||
|
||||
/**
|
||||
* @returns Results<T>
|
||||
*/
|
||||
linkingObjects<T>(objectType: string, property: string): Results<T>;
|
||||
}
|
||||
|
||||
const Object: {
|
||||
|
|
|
@ -52,6 +52,7 @@ struct RealmObjectClass : ClassDefinition<T, realm::Object> {
|
|||
|
||||
static void is_valid(ContextType, FunctionType, ObjectType, size_t, const ValueType [], ReturnValue &);
|
||||
static void get_object_schema(ContextType, FunctionType, ObjectType, size_t, const ValueType [], ReturnValue &);
|
||||
static void linking_objects(ContextType, FunctionType, ObjectType, size_t, const ValueType [], ReturnValue &);
|
||||
|
||||
const std::string name = "RealmObject";
|
||||
|
||||
|
@ -64,6 +65,7 @@ struct RealmObjectClass : ClassDefinition<T, realm::Object> {
|
|||
MethodMap<T> const methods = {
|
||||
{"isValid", wrap<is_valid>},
|
||||
{"objectSchema", wrap<get_object_schema>},
|
||||
{"linkingObjects", wrap<linking_objects>},
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -152,3 +154,37 @@ std::vector<String<T>> RealmObjectClass<T>::get_property_names(ContextType ctx,
|
|||
|
||||
} // js
|
||||
} // realm
|
||||
|
||||
// move this all the way here because it needs to include "js_results.hpp" which in turn includes this file
|
||||
|
||||
#include "js_results.hpp"
|
||||
|
||||
template<typename T>
|
||||
void realm::js::RealmObjectClass<T>::linking_objects(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 2);
|
||||
|
||||
std::string object_type = Value::validated_to_string(ctx, arguments[0], "objectType");
|
||||
std::string property_name = Value::validated_to_string(ctx, arguments[1], "property");
|
||||
|
||||
auto object = get_internal<T, RealmObjectClass<T>>(this_object);
|
||||
|
||||
auto target_object_schema = object->realm()->schema().find(object_type);
|
||||
if (target_object_schema == object->realm()->schema().end()) {
|
||||
throw std::logic_error(util::format("Could not find schema for type '%1'", object_type));
|
||||
}
|
||||
|
||||
auto link_property = target_object_schema->property_for_name(property_name);
|
||||
if (!link_property) {
|
||||
throw std::logic_error(util::format("Type '%1' does not contain property '%2'", object_type, property_name));
|
||||
}
|
||||
|
||||
if (link_property->object_type != object->get_object_schema().name) {
|
||||
throw std::logic_error(util::format("'%1.%2' is not a relationship to '%3'", object_type, property_name, object->get_object_schema().name));
|
||||
}
|
||||
|
||||
realm::TableRef table = ObjectStore::table_for_object_type(object->realm()->read_group(), target_object_schema->name);
|
||||
auto row = object->row();
|
||||
auto tv = row.get_table()->get_backlink_view(row.get_index(), table.get(), link_property->table_column);
|
||||
|
||||
return_value.set(ResultsClass<T>::create_instance(ctx, realm::Results(object->realm(), std::move(tv))));
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ Property Schema<T>::parse_property(ContextType ctx, ValueType attributes, std::s
|
|||
static const String type_string = "type";
|
||||
static const String object_type_string = "objectType";
|
||||
static const String optional_string = "optional";
|
||||
static const String property_string = "property";
|
||||
|
||||
Property prop;
|
||||
prop.name = property_name;
|
||||
|
@ -123,20 +124,29 @@ Property Schema<T>::parse_property(ContextType ctx, ValueType attributes, std::s
|
|||
prop.type = realm::PropertyType::Array;
|
||||
prop.object_type = Object::validated_get_string(ctx, property_object, object_type_string);
|
||||
}
|
||||
else {
|
||||
else if (type == "linkingObjects") {
|
||||
prop.type = realm::PropertyType::LinkingObjects;
|
||||
|
||||
if (!Value::is_valid(property_object)) {
|
||||
throw std::runtime_error("Object property must specify 'objectType'");
|
||||
}
|
||||
prop.object_type = Object::validated_get_string(ctx, property_object, object_type_string);
|
||||
prop.link_origin_property_name = Object::validated_get_string(ctx, property_object, property_string);
|
||||
}
|
||||
else if (type == "object") {
|
||||
prop.type = realm::PropertyType::Object;
|
||||
prop.is_nullable = true;
|
||||
|
||||
// The type could either be 'object' or the name of another object type in the same schema.
|
||||
if (type == "object") {
|
||||
if (!Value::is_valid(property_object)) {
|
||||
throw std::runtime_error("Object property must specify 'objectType'");
|
||||
}
|
||||
prop.object_type = Object::validated_get_string(ctx, property_object, object_type_string);
|
||||
}
|
||||
else {
|
||||
prop.object_type = type;
|
||||
|
||||
if (!Value::is_valid(property_object)) {
|
||||
throw std::runtime_error("Object property must specify 'objectType'");
|
||||
}
|
||||
prop.object_type = Object::validated_get_string(ctx, property_object, object_type_string);
|
||||
}
|
||||
else {
|
||||
// The type could be the name of another object type in the same schema.
|
||||
prop.type = realm::PropertyType::Object;
|
||||
prop.is_nullable = true;
|
||||
prop.object_type = type;
|
||||
}
|
||||
|
||||
if (Value::is_valid(property_object)) {
|
||||
|
@ -177,14 +187,27 @@ ObjectSchema Schema<T>::parse_object_schema(ContextType ctx, ObjectType object_s
|
|||
for (uint32_t i = 0; i < length; i++) {
|
||||
ObjectType property_object = Object::validated_get_object(ctx, properties_object, i);
|
||||
std::string property_name = Object::validated_get_string(ctx, property_object, name_string);
|
||||
object_schema.persisted_properties.emplace_back(parse_property(ctx, property_object, property_name, object_defaults));
|
||||
Property property = parse_property(ctx, property_object, property_name, object_defaults);
|
||||
if (property.type == realm::PropertyType::LinkingObjects) {
|
||||
object_schema.computed_properties.emplace_back(std::move(property));
|
||||
}
|
||||
else {
|
||||
object_schema.persisted_properties.emplace_back(std::move(property));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto property_names = Object::get_property_names(ctx, properties_object);
|
||||
for (auto &property_name : property_names) {
|
||||
ValueType property_value = Object::get_property(ctx, properties_object, property_name);
|
||||
object_schema.persisted_properties.emplace_back(parse_property(ctx, property_value, property_name, object_defaults));
|
||||
Property property = parse_property(ctx, property_value, property_name, object_defaults);
|
||||
if (property.type == realm::PropertyType::LinkingObjects) {
|
||||
object_schema.computed_properties.emplace_back(std::move(property));
|
||||
}
|
||||
else {
|
||||
object_schema.persisted_properties.emplace_back(std::move(property));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,6 +266,9 @@ typename T::Object Schema<T>::object_for_object_schema(ContextType ctx, const Ob
|
|||
for (auto& property : object_schema.persisted_properties) {
|
||||
Object::set_property(ctx, properties, property.name, object_for_property(ctx, property));
|
||||
}
|
||||
for (auto& property : object_schema.computed_properties) {
|
||||
Object::set_property(ctx, properties, property.name, object_for_property(ctx, property));
|
||||
}
|
||||
|
||||
static const String properties_string = "properties";
|
||||
Object::set_property(ctx, object, properties_string, properties);
|
||||
|
@ -271,6 +297,11 @@ typename T::Object Schema<T>::object_for_property(ContextType ctx, const Propert
|
|||
Object::set_property(ctx, object, object_type_string, Value::from_string(ctx, property.object_type));
|
||||
}
|
||||
|
||||
static const String property_string = "property";
|
||||
if (property.type == realm::PropertyType::LinkingObjects) {
|
||||
Object::set_property(ctx, object, property_string, Value::from_string(ctx, property.link_origin_property_name));
|
||||
}
|
||||
|
||||
static const String indexed_string = "indexed";
|
||||
if (property.is_indexed) {
|
||||
Object::set_property(ctx, object, indexed_string, Value::from_boolean(ctx, true));
|
||||
|
|
|
@ -462,6 +462,10 @@ json RPCServer::serialize_object_schema(const realm::ObjectSchema &object_schema
|
|||
for (auto &prop : object_schema.persisted_properties) {
|
||||
properties.push_back(prop.name);
|
||||
}
|
||||
|
||||
for (auto &prop : object_schema.computed_properties) {
|
||||
properties.push_back(prop.name);
|
||||
}
|
||||
|
||||
return {
|
||||
{"name", object_schema.name},
|
||||
|
|
|
@ -22,6 +22,7 @@ var Realm = require('realm');
|
|||
|
||||
var TESTS = {
|
||||
ListTests: require('./list-tests'),
|
||||
LinkingObjectsTests: require('./linkingobjects-tests'),
|
||||
ObjectTests: require('./object-tests'),
|
||||
RealmTests: require('./realm-tests'),
|
||||
ResultsTests: require('./results-tests'),
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2017 Realm Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
'use strict';
|
||||
|
||||
var Realm = require('realm');
|
||||
var TestCase = require('./asserts');
|
||||
var schemas = require('./schemas');
|
||||
|
||||
function names(results) {
|
||||
return results.map(function(object) {
|
||||
return object.name;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
testBasics: function() {
|
||||
var realm = new Realm({schema: [schemas.PersonObject]});
|
||||
|
||||
var olivier, oliviersParents;
|
||||
realm.write(function() {
|
||||
olivier = realm.create('PersonObject', {name: 'Olivier', age: 0});
|
||||
realm.create('PersonObject', {name: 'Christine', age: 25, children: [olivier]});
|
||||
oliviersParents = olivier.parents;
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine']);
|
||||
});
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine']);
|
||||
|
||||
var jp;
|
||||
realm.write(function() {
|
||||
jp = realm.create('PersonObject', {name: 'JP', age: 28, children: [olivier]});
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine', 'JP']);
|
||||
});
|
||||
|
||||
realm.write(function() {
|
||||
realm.delete(olivier);
|
||||
|
||||
TestCase.assertEqual(oliviersParents.length, 0);
|
||||
});
|
||||
},
|
||||
|
||||
testFilteredLinkingObjects: function() {
|
||||
var realm = new Realm({schema: [schemas.PersonObject]});
|
||||
|
||||
var christine, olivier, oliviersParents;
|
||||
realm.write(function() {
|
||||
olivier = realm.create('PersonObject', {name: 'Olivier', age: 0});
|
||||
christine = realm.create('PersonObject', {name: 'Christine', age: 25, children: [olivier]});
|
||||
realm.create('PersonObject', {name: 'JP', age: 28, children: [olivier]});
|
||||
oliviersParents = olivier.parents;
|
||||
});
|
||||
|
||||
// Three separate queries so that accessing a property on one doesn't invalidate testing of other properties.
|
||||
var resultsA = oliviersParents.filtered('age > 25');
|
||||
var resultsB = oliviersParents.filtered('age > 25');
|
||||
var resultsC = oliviersParents.filtered('age > 25');
|
||||
|
||||
realm.write(function() {
|
||||
var removed = christine.children.splice(0);
|
||||
TestCase.assertEqual(removed.length, 1);
|
||||
});
|
||||
|
||||
TestCase.assertEqual(resultsA.length, 1);
|
||||
TestCase.assertEqual(resultsB.filtered("name = 'Christine'").length, 0);
|
||||
TestCase.assertArraysEqual(names(resultsC), ['JP']);
|
||||
},
|
||||
|
||||
testMethod: function() {
|
||||
var realm = new Realm({schema: [schemas.PersonObject]});
|
||||
|
||||
var person;
|
||||
realm.write(function () {
|
||||
person = realm.create('PersonObject', { name: 'Person 1', age: 50 });
|
||||
});
|
||||
|
||||
TestCase.assertThrows(() => person.linkingObjects('NoSuchSchema', 'noSuchProperty'),
|
||||
"Could not find schema for type 'NoSuchSchema'");
|
||||
|
||||
TestCase.assertThrows(() => person.linkingObjects('PersonObject', 'noSuchProperty'),
|
||||
"Type 'PersonObject' does not contain property 'noSuchProperty'");
|
||||
|
||||
TestCase.assertThrows(() => person.linkingObjects('PersonObject', 'name'),
|
||||
"'PersonObject.name' is not a relationship to 'PersonObject'");
|
||||
|
||||
var olivier, oliviersParents;
|
||||
realm.write(function() {
|
||||
olivier = realm.create('PersonObject', {name: 'Olivier', age: 0});
|
||||
realm.create('PersonObject', {name: 'Christine', age: 25, children: [olivier]});
|
||||
oliviersParents = olivier.linkingObjects('PersonObject', 'children');
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine']);
|
||||
});
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine']);
|
||||
|
||||
var jp;
|
||||
realm.write(function() {
|
||||
jp = realm.create('PersonObject', {name: 'JP', age: 28, children: [olivier]});
|
||||
|
||||
TestCase.assertArraysEqual(names(oliviersParents), ['Christine', 'JP']);
|
||||
});
|
||||
|
||||
realm.write(function() {
|
||||
realm.delete(olivier);
|
||||
|
||||
TestCase.assertEqual(oliviersParents.length, 0);
|
||||
});
|
||||
},
|
||||
};
|
|
@ -123,6 +123,43 @@ module.exports = {
|
|||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [{properties: {intCol: 'int'}}]});
|
||||
}, 'The schema should be an array of ObjectSchema objects');
|
||||
|
||||
// linkingObjects property where the source property is missing
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [{
|
||||
name: 'InvalidObject',
|
||||
properties: {
|
||||
linkingObjects: {type:'linkingObjects', objectType: 'InvalidObject', property: 'nosuchproperty'}
|
||||
}
|
||||
}]});
|
||||
}, "Property 'InvalidObject.nosuchproperty' declared as origin of linking objects property 'InvalidObject.linkingObjects' does not exist");
|
||||
|
||||
// linkingObjects property where the source property is not a link
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [{
|
||||
name: 'InvalidObject',
|
||||
properties: {
|
||||
integer: 'int',
|
||||
linkingObjects: {type:'linkingObjects', objectType: 'InvalidObject', property: 'integer'}
|
||||
}
|
||||
}]});
|
||||
}, "Property 'InvalidObject.integer' declared as origin of linking objects property 'InvalidObject.linkingObjects' is not a link")
|
||||
|
||||
// linkingObjects property where the source property links elsewhere
|
||||
TestCase.assertThrows(function() {
|
||||
new Realm({schema: [{
|
||||
name: 'InvalidObject',
|
||||
properties: {
|
||||
link: 'IntObject',
|
||||
linkingObjects: {type:'linkingObjects', objectType: 'InvalidObject', property: 'link'}
|
||||
}
|
||||
}, {
|
||||
name: 'IntObject',
|
||||
properties: {
|
||||
integer: 'int'
|
||||
}
|
||||
}]});
|
||||
}, "Property 'InvalidObject.link' declared as origin of linking objects property 'InvalidObject.linkingObjects' links to type 'IntObject'")
|
||||
},
|
||||
|
||||
testRealmConstructorReadOnly: function() {
|
||||
|
@ -178,7 +215,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
testRealmWrite: function() {
|
||||
var realm = new Realm({schema: [schemas.IntPrimary, schemas.AllTypes, schemas.TestObject]});
|
||||
var realm = new Realm({schema: [schemas.IntPrimary, schemas.AllTypes, schemas.TestObject, schemas.LinkToAllTypes]});
|
||||
|
||||
// exceptions should be propogated
|
||||
TestCase.assertThrows(function() {
|
||||
|
@ -271,7 +308,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
testRealmCreateUpsert: function() {
|
||||
var realm = new Realm({schema: [schemas.IntPrimary, schemas.StringPrimary, schemas.AllTypes, schemas.TestObject]});
|
||||
var realm = new Realm({schema: [schemas.IntPrimary, schemas.StringPrimary, schemas.AllTypes, schemas.TestObject, schemas.LinkToAllTypes]});
|
||||
realm.write(function() {
|
||||
var values = {
|
||||
primaryCol: '0',
|
||||
|
@ -789,7 +826,7 @@ module.exports = {
|
|||
|
||||
testSchema: function() {
|
||||
var originalSchema = [schemas.TestObject, schemas.BasicTypes, schemas.NullableBasicTypes, schemas.IndexedTypes, schemas.IntPrimary,
|
||||
schemas.PersonObject, schemas.LinkTypes];
|
||||
schemas.PersonObject, schemas.LinkTypes, schemas.LinkingObjectsObject];
|
||||
|
||||
var schemaMap = {};
|
||||
originalSchema.forEach(function(objectSchema) {
|
||||
|
@ -827,6 +864,11 @@ module.exports = {
|
|||
TestCase.assertEqual(prop1.objectType, prop2.objectType);
|
||||
TestCase.assertEqual(prop1.optional, undefined);
|
||||
}
|
||||
else if (prop1.type == 'linking objects') {
|
||||
TestCase.assertEqual(prop1.objectType, prop2.objectType);
|
||||
TestCase.assertEqual(prop1.property, prop2.property);
|
||||
TestCase.assertEqual(prop1.optional, undefined);
|
||||
}
|
||||
else {
|
||||
TestCase.assertEqual(prop1.type, isString(prop2) ? prop2 : prop2.type);
|
||||
TestCase.assertEqual(prop1.optional, prop2.optional || undefined);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const Realm = require('realm');
|
||||
|
||||
exports.TestObject = {
|
||||
name: 'TestObject',
|
||||
properties: {
|
||||
|
@ -29,9 +31,11 @@ function PersonObject() {}
|
|||
PersonObject.schema = {
|
||||
name: 'PersonObject',
|
||||
properties: {
|
||||
name: 'string',
|
||||
age: 'double',
|
||||
married: {type: 'bool', default: false},
|
||||
name: 'string',
|
||||
age: 'double',
|
||||
married: {type: 'bool', default: false},
|
||||
children: {type: 'list', objectType: 'PersonObject'},
|
||||
parents: {type: 'linkingObjects', objectType: 'PersonObject', property: 'children'},
|
||||
}
|
||||
};
|
||||
PersonObject.prototype.description = function() {
|
||||
|
@ -40,6 +44,8 @@ PersonObject.prototype.description = function() {
|
|||
PersonObject.prototype.toString = function() {
|
||||
return this.name;
|
||||
};
|
||||
Object.setPrototypeOf(PersonObject, Realm.Object);
|
||||
Object.setPrototypeOf(PersonObject.prototype, Realm.Object.prototype);
|
||||
exports.PersonObject = PersonObject;
|
||||
|
||||
exports.PersonList = {
|
||||
|
@ -117,19 +123,27 @@ exports.AllTypes = {
|
|||
name: 'AllTypesObject',
|
||||
primaryKey: 'primaryCol',
|
||||
properties: {
|
||||
primaryCol: 'string',
|
||||
boolCol: 'bool',
|
||||
intCol: 'int',
|
||||
floatCol: 'float',
|
||||
doubleCol: 'double',
|
||||
stringCol: 'string',
|
||||
dateCol: 'date',
|
||||
dataCol: 'data',
|
||||
objectCol: 'TestObject',
|
||||
arrayCol: {type: 'list', objectType: 'TestObject'},
|
||||
primaryCol: 'string',
|
||||
boolCol: 'bool',
|
||||
intCol: 'int',
|
||||
floatCol: 'float',
|
||||
doubleCol: 'double',
|
||||
stringCol: 'string',
|
||||
dateCol: 'date',
|
||||
dataCol: 'data',
|
||||
objectCol: 'TestObject',
|
||||
arrayCol: {type: 'list', objectType: 'TestObject'},
|
||||
linkingObjectsCol: {type: 'linkingObjects', objectType: 'LinkToAllTypesObject', property: 'allTypesCol'},
|
||||
}
|
||||
};
|
||||
|
||||
exports.LinkToAllTypes = {
|
||||
name: 'LinkToAllTypesObject',
|
||||
properties: {
|
||||
allTypesCol: 'AllTypesObject',
|
||||
}
|
||||
}
|
||||
|
||||
exports.DefaultValues = {
|
||||
name: 'DefaultValuesObject',
|
||||
properties: {
|
||||
|
@ -185,3 +199,12 @@ exports.DateObject = {
|
|||
nullDate: { type: 'date', optional: true }
|
||||
}
|
||||
};
|
||||
|
||||
exports.LinkingObjectsObject = {
|
||||
name: 'LinkingObjectsObject',
|
||||
properties: {
|
||||
value: 'int',
|
||||
links: {type: 'list', objectType: 'LinkingObjectsObject'},
|
||||
linkingObjects: {type: 'linkingObjects', objectType: 'LinkingObjectsObject', property: 'links'}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue