Added method to find index of object in collections (#1094)
* Added method to find index of object in collections * rework as the indexOf method
This commit is contained in:
parent
beda604425
commit
db4e184524
|
@ -4,7 +4,7 @@ vNext Release notes (TBD)
|
|||
* None
|
||||
|
||||
### Enhancements
|
||||
* None.
|
||||
* Added `indexOf()` method on `Realm.Results` and `Realm.List` that returns the index of the object in the collection.
|
||||
|
||||
### Bug fixes
|
||||
* Fix opening synced realms with a logged-in admin user.
|
||||
|
|
|
@ -164,6 +164,16 @@ class Collection {
|
|||
*/
|
||||
findIndex(callback, thisArg) {}
|
||||
|
||||
/**
|
||||
Finds the index of the given object in the collection.
|
||||
* @param {Realm.Object} [object] - The object to search for in the collection.
|
||||
* @throws {Error} If the argument does not belong to the realm.
|
||||
* @returns {number} representing the index where the object was found, or `-1`
|
||||
* if not in collection.
|
||||
* @since 1.8.2
|
||||
*/
|
||||
indexOf(object) {}
|
||||
|
||||
/**
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach Array.prototype.forEach}
|
||||
* @param {function} callback - Function to execute on each object in the collection.
|
||||
|
|
|
@ -30,7 +30,8 @@ createMethods(List.prototype, objectTypes.LIST, [
|
|||
'filtered',
|
||||
'sorted',
|
||||
'snapshot',
|
||||
'isValid',
|
||||
'isValid',
|
||||
'indexOf',
|
||||
'addListener',
|
||||
'removeListener',
|
||||
'removeAllListeners',
|
||||
|
|
|
@ -30,6 +30,7 @@ createMethods(Results.prototype, objectTypes.RESULTS, [
|
|||
'sorted',
|
||||
'snapshot',
|
||||
'isValid',
|
||||
'indexOf',
|
||||
'addListener',
|
||||
'removeListener',
|
||||
'removeAllListeners',
|
||||
|
|
|
@ -36,7 +36,6 @@ Object.defineProperty(iteratorPrototype, Symbol.iterator, {
|
|||
'concat',
|
||||
'join',
|
||||
'slice',
|
||||
'indexOf',
|
||||
'lastIndexOf',
|
||||
'every',
|
||||
'some',
|
||||
|
|
|
@ -72,7 +72,8 @@ struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
|||
static void filtered(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void sorted(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void is_valid(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
||||
static void index_of(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
||||
// observable
|
||||
static void add_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void remove_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
@ -90,6 +91,7 @@ struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
|||
{"filtered", wrap<filtered>},
|
||||
{"sorted", wrap<sorted>},
|
||||
{"isValid", wrap<is_valid>},
|
||||
{"indexOf", wrap<index_of>},
|
||||
{"addListener", wrap<add_listener>},
|
||||
{"removeListener", wrap<remove_listener>},
|
||||
{"removeAllListeners", wrap<remove_all_listeners>},
|
||||
|
@ -256,7 +258,33 @@ template<typename T>
|
|||
void ListClass<T>::is_valid(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
return_value.set(get_internal<T, ListClass<T>>(this_object)->is_valid());
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void ListClass<T>::index_of(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 1);
|
||||
|
||||
ObjectType arg = Value::validated_to_object(ctx, arguments[0]);
|
||||
if (Object::template is_instance<RealmObjectClass<T>>(ctx, arg)) {
|
||||
auto object = get_internal<T, RealmObjectClass<T>>(arg);
|
||||
if (!object->is_valid()) {
|
||||
throw std::runtime_error("Object is invalid. Either it has been previously deleted or the Realm it belongs to has been closed.");
|
||||
}
|
||||
|
||||
auto list = get_internal<T, ListClass<T>>(this_object);
|
||||
size_t ndx = list->find(object->row());
|
||||
|
||||
if (ndx == realm::not_found) {
|
||||
return_value.set(-1);
|
||||
}
|
||||
else {
|
||||
return_value.set((uint32_t)ndx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return_value.set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ListClass<T>::add_listener(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 1);
|
||||
|
|
|
@ -74,6 +74,8 @@ struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<
|
|||
static void sorted(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void is_valid(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
||||
static void index_of(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
||||
// observable
|
||||
static void add_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
static void remove_listener(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
@ -89,6 +91,7 @@ struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<
|
|||
{"addListener", wrap<add_listener>},
|
||||
{"removeListener", wrap<remove_listener>},
|
||||
{"removeAllListeners", wrap<remove_all_listeners>},
|
||||
{"indexOf", wrap<index_of>},
|
||||
};
|
||||
|
||||
PropertyMap<T> const properties = {
|
||||
|
@ -238,6 +241,38 @@ void ResultsClass<T>::is_valid(ContextType ctx, FunctionType, ObjectType this_ob
|
|||
return_value.set(get_internal<T, ResultsClass<T>>(this_object)->is_valid());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ResultsClass<T>::index_of(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 1);
|
||||
|
||||
ObjectType arg = Value::validated_to_object(ctx, arguments[0]);
|
||||
if (Object::template is_instance<RealmObjectClass<T>>(ctx, arg)) {
|
||||
auto object = get_internal<T, RealmObjectClass<T>>(arg);
|
||||
if (!object->is_valid()) {
|
||||
throw std::runtime_error("Object is invalid. Either it has been previously deleted or the Realm it belongs to has been closed.");
|
||||
}
|
||||
|
||||
size_t ndx;
|
||||
try {
|
||||
auto results = get_internal<T, ResultsClass<T>>(this_object);
|
||||
ndx = results->index_of(object->row());
|
||||
}
|
||||
catch (realm::Results::IncorrectTableException &) {
|
||||
throw std::runtime_error("Object type does not match the type contained in result");
|
||||
}
|
||||
|
||||
if (ndx == realm::not_found) {
|
||||
return_value.set(-1);
|
||||
}
|
||||
else {
|
||||
return_value.set((uint32_t)ndx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return_value.set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ResultsClass<T>::add_listener(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 1);
|
||||
|
|
|
@ -583,6 +583,7 @@ module.exports = {
|
|||
|
||||
var index = list.findIndex(function(p) {return p.name == 'Tim'});
|
||||
TestCase.assertEqual(index, 1);
|
||||
TestCase.assertEqual(list.indexOf(list[index]), index);
|
||||
|
||||
TestCase.assertEqual(list.reduce(function(n, p) {return n + p.age}, 0), 33);
|
||||
TestCase.assertEqual(list.reduceRight(function(n, p) {return n + p.age}, 0), 33);
|
||||
|
|
|
@ -383,6 +383,42 @@ module.exports = {
|
|||
TestCase.assertEqual(snapshot.length, 0);
|
||||
});
|
||||
},
|
||||
|
||||
testResultsFindIndexOfObject: function() {
|
||||
var realm = new Realm({schema: [schemas.TestObject]});
|
||||
|
||||
var object1, object2, object3;
|
||||
realm.write(function() {
|
||||
object1 = realm.create('TestObject', {doubleCol: 1});
|
||||
object2 = realm.create('TestObject', {doubleCol: 2});
|
||||
object3 = realm.create('TestObject', {doubleCol: 2});
|
||||
});
|
||||
|
||||
// Search in base table
|
||||
const objects = realm.objects('TestObject');
|
||||
TestCase.assertEqual(objects.indexOf(object1), 0);
|
||||
TestCase.assertEqual(objects.indexOf(object2), 1);
|
||||
TestCase.assertEqual(objects.indexOf(object3), 2);
|
||||
|
||||
// Search in filtered query
|
||||
const results = objects.filtered("doubleCol == 2");
|
||||
TestCase.assertEqual(results.indexOf(object1), -1);
|
||||
TestCase.assertEqual(results.indexOf(object2), 0);
|
||||
TestCase.assertEqual(results.indexOf(object3), 1);
|
||||
|
||||
const nonRealmObject = {test: "this is an object"};
|
||||
TestCase.assertEqual(objects.indexOf(nonRealmObject), -1);
|
||||
|
||||
// Searching for object from the wrong realm
|
||||
var realm2 = new Realm({path: '2.realm', schema: realm.schema});
|
||||
var object4;
|
||||
realm2.write(function() {
|
||||
object4 = realm2.create('TestObject', {doubleCol: 1});
|
||||
});
|
||||
TestCase.assertThrows(function() {
|
||||
objects.indexOf(object4);
|
||||
});
|
||||
},
|
||||
|
||||
testAddListener: function() {
|
||||
return new Promise((resolve, _reject) => {
|
||||
|
@ -408,4 +444,6 @@ module.exports = {
|
|||
});
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue