support defaults
This commit is contained in:
parent
0e665e605e
commit
16be837817
|
@ -120,6 +120,16 @@ template<> JSValueRef RJSAccessor::dict_value_for_key(JSContextRef ctx, JSValueR
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> bool RJSAccessor::has_default_value_for_property(JSContextRef ctx, const ObjectSchema &object_schema, const std::string &prop_name) {
|
||||||
|
ObjectDefaults &defaults = RJSDefaultsForClassName(object_schema.name);
|
||||||
|
return defaults.find(prop_name) != defaults.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx, const ObjectSchema &object_schema, const std::string &prop_name) {
|
||||||
|
ObjectDefaults &defaults = RJSDefaultsForClassName(object_schema.name);
|
||||||
|
return defaults[prop_name];
|
||||||
|
}
|
||||||
|
|
||||||
template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) {
|
template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) {
|
||||||
return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val);
|
return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,11 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#import "RJSUtil.hpp"
|
#import "RJSUtil.hpp"
|
||||||
|
#import <map>
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class Schema;
|
class Schema;
|
||||||
|
using ObjectDefaults = std::map<std::string, JSValueRef>;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSClassRef RJSSchemaClass();
|
JSClassRef RJSSchemaClass();
|
||||||
|
@ -28,3 +30,4 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, realm::Schema *schema);
|
||||||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject);
|
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject);
|
||||||
|
|
||||||
JSValueRef RJSPrototypeForClassName(const std::string &className);
|
JSValueRef RJSPrototypeForClassName(const std::string &className);
|
||||||
|
realm::ObjectDefaults &RJSDefaultsForClassName(const std::string &className);
|
||||||
|
|
|
@ -45,6 +45,11 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, Schema &schema) {
|
||||||
return RJSWrapObject(ctx, RJSSchemaClass(), wrapper);
|
return RJSWrapObject(ctx, RJSSchemaClass(), wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::map<std::string, ObjectDefaults> s_defaults;
|
||||||
|
ObjectDefaults &RJSDefaultsForClassName(const std::string &className) {
|
||||||
|
return s_defaults[className];
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<std::string, JSValueRef> s_prototypes;
|
static std::map<std::string, JSValueRef> s_prototypes;
|
||||||
JSValueRef RJSPrototypeForClassName(const std::string &className) {
|
JSValueRef RJSPrototypeForClassName(const std::string &className) {
|
||||||
return s_prototypes[className];
|
return s_prototypes[className];
|
||||||
|
@ -117,15 +122,24 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
||||||
JSObjectRef propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema object must have a 'properties' array.");
|
JSObjectRef propertiesObject = RJSValidatedObjectProperty(ctx, objectSchemaObject, propertiesString, "ObjectSchema object must have a 'properties' array.");
|
||||||
|
|
||||||
ObjectSchema objectSchema;
|
ObjectSchema objectSchema;
|
||||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
ObjectDefaults defaults;
|
||||||
|
|
||||||
|
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||||
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
||||||
|
|
||||||
size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject);
|
size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject);
|
||||||
for (unsigned int p = 0; p < numProperties; p++) {
|
for (unsigned int p = 0; p < numProperties; p++) {
|
||||||
JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p);
|
JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p);
|
||||||
objectSchema.properties.emplace_back(RJSParseProperty(ctx, property));
|
objectSchema.properties.emplace_back(RJSParseProperty(ctx, property));
|
||||||
|
|
||||||
|
static JSStringRef defaultString = JSStringCreateWithUTF8CString("default");
|
||||||
|
JSValueRef defaultValue = JSObjectGetProperty(ctx, property, defaultString, NULL);
|
||||||
|
if (!JSValueIsUndefined(ctx, defaultValue)) {
|
||||||
|
JSValueProtect(ctx, defaultValue);
|
||||||
|
defaults.emplace(objectSchema.properties.back().name, defaultValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
s_defaults.emplace(objectSchema.name, std::move(defaults));
|
||||||
|
|
||||||
static JSStringRef primaryString = JSStringCreateWithUTF8CString("primaryKey");
|
static JSStringRef primaryString = JSStringCreateWithUTF8CString("primaryKey");
|
||||||
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
||||||
|
@ -141,7 +155,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
||||||
// store prototype
|
// store prototype
|
||||||
if (prototypeObject) {
|
if (prototypeObject) {
|
||||||
JSValueProtect(ctx, prototypeObject);
|
JSValueProtect(ctx, prototypeObject);
|
||||||
s_prototypes[objectSchema.name] = prototypeObject;
|
s_prototypes[objectSchema.name] = std::move(prototypeObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
return objectSchema;
|
return objectSchema;
|
||||||
|
@ -158,3 +172,4 @@ realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) {
|
||||||
|
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,9 @@ namespace realm {
|
||||||
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
||||||
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
|
||||||
|
|
||||||
|
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
|
||||||
|
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
|
||||||
|
|
||||||
static bool to_bool(ContextType ctx, ValueType &val);
|
static bool to_bool(ContextType ctx, ValueType &val);
|
||||||
static long long to_long(ContextType ctx, ValueType &val);
|
static long long to_long(ContextType ctx, ValueType &val);
|
||||||
static float to_float(ContextType ctx, ValueType &val);
|
static float to_float(ContextType ctx, ValueType &val);
|
||||||
|
@ -184,14 +187,18 @@ namespace realm {
|
||||||
// populate
|
// populate
|
||||||
Object object(realm, object_schema, table->get(row_index));
|
Object object(realm, object_schema, table->get(row_index));
|
||||||
for (Property &prop : object_schema.properties) {
|
for (Property &prop : object_schema.properties) {
|
||||||
if (Accessor::dict_has_value_for_key(ctx, value, prop.name)) {
|
if (created || !prop.is_primary) {
|
||||||
if (created || !prop.is_primary) {
|
if (Accessor::dict_has_value_for_key(ctx, value, prop.name)) {
|
||||||
ValueType prop_value = Accessor::dict_value_for_key(ctx, value, prop.name);
|
object.set_property_value_impl(ctx, prop, Accessor::dict_value_for_key(ctx, value, prop.name), try_update);
|
||||||
object.set_property_value_impl(ctx, prop, prop_value, try_update);
|
}
|
||||||
|
else if (created) {
|
||||||
|
if (Accessor::has_default_value_for_property(ctx, object_schema, prop.name)) {
|
||||||
|
object.set_property_value_impl(ctx, prop, Accessor::default_value_for_property(ctx, object_schema, prop.name), try_update);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw std::runtime_error("Missing property value for property " + prop.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (created) {
|
|
||||||
throw std::runtime_error("Missing property value for property " + prop.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return object;
|
return object;
|
||||||
|
|
|
@ -86,7 +86,7 @@ var ObjectTests = {
|
||||||
var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]});
|
var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]});
|
||||||
var obj = null;
|
var obj = null;
|
||||||
realm.write(function() {
|
realm.write(function() {
|
||||||
obj = realm.create('LinkTypesObject', [[1], undefined, [[3]]]);
|
obj = realm.create('LinkTypesObject', [[1], null, [[3]]]);
|
||||||
});
|
});
|
||||||
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ var ObjectTests = {
|
||||||
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
||||||
|
|
||||||
realm.write(function() {
|
realm.write(function() {
|
||||||
obj.objectCol = undefined;
|
obj.objectCol = null;
|
||||||
obj.objectCol1 = null;
|
obj.objectCol1 = null;
|
||||||
});
|
});
|
||||||
TestCase.assertEqual(obj.objectCol, null);
|
TestCase.assertEqual(obj.objectCol, null);
|
||||||
|
|
|
@ -142,6 +142,24 @@ var RealmTests = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
testRealmCreateWithDefaults: function() {
|
||||||
|
var realm = new Realm({schema: [DefaultValuesObjectSchema, TestObjectSchema]});
|
||||||
|
realm.write(function() {
|
||||||
|
var obj = realm.create('DefaultValuesObject', {});
|
||||||
|
TestCase.assertEqual(obj.boolCol, DefaultValuesObjectSchema.properties[0].default);
|
||||||
|
TestCase.assertEqual(obj.intCol, DefaultValuesObjectSchema.properties[1].default);
|
||||||
|
TestCase.assertEqualWithTolerance(obj.floatCol, DefaultValuesObjectSchema.properties[2].default, 0.000001);
|
||||||
|
TestCase.assertEqual(obj.doubleCol, DefaultValuesObjectSchema.properties[3].default);
|
||||||
|
TestCase.assertEqual(obj.stringCol, DefaultValuesObjectSchema.properties[4].default);
|
||||||
|
TestCase.assertEqual(obj.dateCol.getTime(), DefaultValuesObjectSchema.properties[5].default.getTime());
|
||||||
|
TestCase.assertEqual(obj.dataCol, DefaultValuesObjectSchema.properties[6].default);
|
||||||
|
TestCase.assertEqual(obj.objectCol.doubleCol, DefaultValuesObjectSchema.properties[7].default[0]);
|
||||||
|
TestCase.assertEqual(obj.nullObjectCol, null);
|
||||||
|
TestCase.assertEqual(obj.arrayCol.length, DefaultValuesObjectSchema.properties[9].default.length);
|
||||||
|
TestCase.assertEqual(obj.arrayCol[0].doubleCol, DefaultValuesObjectSchema.properties[9].default[0][0]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
testRealmDelete: function() {
|
testRealmDelete: function() {
|
||||||
var realm = new Realm({schema: [TestObjectSchema]});
|
var realm = new Realm({schema: [TestObjectSchema]});
|
||||||
realm.write(function() {
|
realm.write(function() {
|
||||||
|
|
|
@ -85,3 +85,19 @@ var AllTypesObjectSchema = {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var DefaultValuesObjectSchema = {
|
||||||
|
name: 'DefaultValuesObject',
|
||||||
|
properties: [
|
||||||
|
{name: 'boolCol', type: RealmType.Bool, default: true},
|
||||||
|
{name: 'intCol', type: RealmType.Int, default: -1},
|
||||||
|
{name: 'floatCol', type: RealmType.Float, default: -1.1},
|
||||||
|
{name: 'doubleCol', type: RealmType.Double, default: -1.11},
|
||||||
|
{name: 'stringCol', type: RealmType.String, default: 'defaultString'},
|
||||||
|
{name: 'dateCol', type: RealmType.Date, default: new Date(1.111)},
|
||||||
|
{name: 'dataCol', type: RealmType.Data, default: 'defaultData'},
|
||||||
|
{name: 'objectCol', type: 'TestObject', default: [1]},
|
||||||
|
{name: 'nullObjectCol', type: 'TestObject', default: null},
|
||||||
|
{name: 'arrayCol', type: RealmType.Array, objectType: 'TestObject', default: [[2]]},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue