Allow sortedBy to accept array of properties
It now optionally accepts an array of properties for both parameters and the tests have been updated to reflect new capabilities.
This commit is contained in:
parent
249bcd8f3f
commit
76865d0da4
|
@ -95,19 +95,50 @@ JSValueRef ResultsSorted(JSContextRef ctx, JSObjectRef function, JSObjectRef thi
|
|||
try {
|
||||
Results *results = RJSGetInternal<Results *>(thisObject);
|
||||
RJSValidateArgumentRange(argumentCount, 1, 2);
|
||||
size_t prop_count;
|
||||
std::vector<std::string> prop_names;
|
||||
|
||||
std::string propName = RJSValidatedStringForValue(ctx, arguments[0]);
|
||||
const Property *prop = results->get_object_schema().property_for_name(propName);
|
||||
if (RJSIsValueArray(ctx, arguments[0])) {
|
||||
JSObjectRef js_prop_names = RJSValidatedValueToObject(ctx, arguments[0]);
|
||||
prop_count = RJSValidatedListLength(ctx, js_prop_names);
|
||||
prop_names.resize(prop_count);
|
||||
|
||||
for (unsigned int i = 0; i < prop_count; i++) {
|
||||
prop_names[i] = RJSValidatedStringForValue(ctx, RJSValidatedPropertyAtIndex(ctx, js_prop_names, i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
prop_count = 1;
|
||||
prop_names.push_back(RJSValidatedStringForValue(ctx, arguments[0]));
|
||||
}
|
||||
|
||||
std::vector<size_t> columns(prop_count);
|
||||
std::vector<bool> ascending(prop_count, true);
|
||||
size_t index = 0;
|
||||
|
||||
for (std::string prop_name : prop_names) {
|
||||
const Property *prop = results->get_object_schema().property_for_name(prop_name);
|
||||
if (!prop) {
|
||||
throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->get_object_schema().name + "'");
|
||||
throw std::runtime_error("Property '" + prop_name + "' does not exist on object type '" + results->get_object_schema().name + "'");
|
||||
}
|
||||
columns[index++] = prop->table_column;
|
||||
}
|
||||
|
||||
bool ascending = true;
|
||||
if (argumentCount == 2) {
|
||||
ascending = !JSValueToBoolean(ctx, arguments[1]);
|
||||
if (RJSIsValueArray(ctx, arguments[1])) {
|
||||
JSObjectRef js_reverse = RJSValidatedValueToObject(ctx, arguments[1]);
|
||||
size_t js_reverse_count = std::min(RJSValidatedListLength(ctx, js_reverse), prop_count);
|
||||
|
||||
for (unsigned int i = 0; i < js_reverse_count; i++) {
|
||||
ascending[i] = !JSValueToBoolean(ctx, RJSValidatedPropertyAtIndex(ctx, js_reverse, i));
|
||||
}
|
||||
}
|
||||
else if (JSValueToBoolean(ctx, arguments[1])) {
|
||||
ascending.assign(prop_count, false);
|
||||
}
|
||||
}
|
||||
|
||||
results = new Results(results->sort({{prop->table_column}, {ascending}}));
|
||||
results = new Results(results->sort({std::move(columns), std::move(ascending)}));
|
||||
return RJSWrapObject<Results *>(ctx, RJSResultsClass(), results);
|
||||
}
|
||||
catch (std::exception &exp) {
|
||||
|
|
|
@ -143,6 +143,15 @@ static inline JSValueRef RJSValidatedPropertyValue(JSContextRef ctx, JSObjectRef
|
|||
return propertyValue;
|
||||
}
|
||||
|
||||
static inline JSValueRef RJSValidatedPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned int index) {
|
||||
JSValueRef exception = NULL;
|
||||
JSValueRef propertyValue = JSObjectGetPropertyAtIndex(ctx, object, index, &exception);
|
||||
if (exception) {
|
||||
throw RJSException(ctx, exception);
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
static inline JSObjectRef RJSValidatedObjectProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property, const char *err = NULL) {
|
||||
JSValueRef propertyValue = RJSValidatedPropertyValue(ctx, object, property);
|
||||
if (JSValueIsUndefined(ctx, propertyValue)) {
|
||||
|
@ -152,12 +161,7 @@ static inline JSObjectRef RJSValidatedObjectProperty(JSContextRef ctx, JSObjectR
|
|||
}
|
||||
|
||||
static inline JSObjectRef RJSValidatedObjectAtIndex(JSContextRef ctx, JSObjectRef object, unsigned int index) {
|
||||
JSValueRef exception = NULL;
|
||||
JSValueRef objectValue = JSObjectGetPropertyAtIndex(ctx, object, index, &exception);
|
||||
if (exception) {
|
||||
throw RJSException(ctx, exception);
|
||||
}
|
||||
return RJSValidatedValueToObject(ctx, objectValue);
|
||||
return RJSValidatedValueToObject(ctx, RJSValidatedPropertyAtIndex(ctx, object, index));
|
||||
}
|
||||
|
||||
static inline std::string RJSValidatedStringProperty(JSContextRef ctx, JSObjectRef object, JSStringRef property) {
|
||||
|
|
|
@ -136,29 +136,61 @@ module.exports = BaseTest.extend({
|
|||
});
|
||||
},
|
||||
testSort: function() {
|
||||
var realm = new Realm({schema: [schemas.TestObject]});
|
||||
var objects = realm.objects('TestObject');
|
||||
var realm = new Realm({schema: [schemas.IntPrimary]});
|
||||
var objects = realm.objects('IntPrimaryObject');
|
||||
|
||||
realm.write(function() {
|
||||
realm.create('TestObject', {doubleCol: 2});
|
||||
realm.create('TestObject', {doubleCol: 3});
|
||||
realm.create('TestObject', {doubleCol: 1});
|
||||
realm.create('TestObject', {doubleCol: 4});
|
||||
realm.create('TestObject', {doubleCol: 0});
|
||||
realm.create('IntPrimaryObject', {primaryCol: 2, valueCol: 'a'});
|
||||
realm.create('IntPrimaryObject', {primaryCol: 3, valueCol: 'a'});
|
||||
realm.create('IntPrimaryObject', {primaryCol: 1, valueCol: 'b'});
|
||||
realm.create('IntPrimaryObject', {primaryCol: 4, valueCol: 'c'});
|
||||
realm.create('IntPrimaryObject', {primaryCol: 0, valueCol: 'c'});
|
||||
});
|
||||
|
||||
objects = objects.sortedBy('doubleCol');
|
||||
TestCase.assertEqual(objects[0].doubleCol, 0);
|
||||
TestCase.assertEqual(objects[1].doubleCol, 1);
|
||||
TestCase.assertEqual(objects[2].doubleCol, 2);
|
||||
TestCase.assertEqual(objects[3].doubleCol, 3);
|
||||
TestCase.assertEqual(objects[4].doubleCol, 4);
|
||||
var primaries = function(results, prop) {
|
||||
return Array.prototype.map.call(results, function(object) {
|
||||
return object.primaryCol;
|
||||
});
|
||||
};
|
||||
|
||||
objects = objects.sortedBy('doubleCol', true);
|
||||
TestCase.assertEqual(objects[0].doubleCol, 4);
|
||||
TestCase.assertEqual(objects[1].doubleCol, 3);
|
||||
TestCase.assertEqual(objects[2].doubleCol, 2);
|
||||
TestCase.assertEqual(objects[3].doubleCol, 1);
|
||||
TestCase.assertEqual(objects[4].doubleCol, 0);
|
||||
objects = objects.sortedBy('primaryCol');
|
||||
TestCase.assertArraysEqual(primaries(objects), [0, 1, 2, 3, 4]);
|
||||
|
||||
objects = objects.sortedBy('primaryCol', true);
|
||||
TestCase.assertArraysEqual(primaries(objects), [4, 3, 2, 1, 0]);
|
||||
|
||||
objects = objects.sortedBy(['primaryCol', 'valueCol']);
|
||||
TestCase.assertArraysEqual(primaries(objects), [0, 1, 2, 3, 4]);
|
||||
|
||||
objects = objects.sortedBy(['primaryCol', 'valueCol'], true);
|
||||
TestCase.assertArraysEqual(primaries(objects), [4, 3, 2, 1, 0]);
|
||||
|
||||
objects = objects.sortedBy(['primaryCol', 'valueCol'], [false]);
|
||||
TestCase.assertArraysEqual(primaries(objects), [0, 1, 2, 3, 4]);
|
||||
|
||||
objects = objects.sortedBy(['valueCol', 'primaryCol']);
|
||||
TestCase.assertArraysEqual(primaries(objects), [2, 3, 1, 0, 4]);
|
||||
|
||||
objects = objects.sortedBy(['valueCol', 'primaryCol'], [false, true]);
|
||||
TestCase.assertArraysEqual(primaries(objects), [3, 2, 1, 4, 0]);
|
||||
|
||||
objects = objects.sortedBy(['valueCol', 'primaryCol'], [true, false]);
|
||||
TestCase.assertArraysEqual(primaries(objects), [0, 4, 1, 2, 3]);
|
||||
|
||||
objects = objects.sortedBy(['valueCol', 'primaryCol'], true);
|
||||
TestCase.assertArraysEqual(primaries(objects), [4, 0, 1, 3, 2]);
|
||||
|
||||
TestCase.assertThrows(function() {
|
||||
objects.sortedBy(1);
|
||||
});
|
||||
TestCase.assertThrows(function() {
|
||||
objects.sortedBy([1]);
|
||||
});
|
||||
TestCase.assertThrows(function() {
|
||||
objects.sortedBy('fish');
|
||||
});
|
||||
TestCase.assertThrows(function() {
|
||||
objects.sortedBy(['valueCol', 'fish']);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue