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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#import "RJSUtil.hpp"
|
||||
#import <map>
|
||||
|
||||
namespace realm {
|
||||
class Schema;
|
||||
using ObjectDefaults = std::map<std::string, JSValueRef>;
|
||||
}
|
||||
|
||||
JSClassRef RJSSchemaClass();
|
||||
|
@ -28,3 +30,4 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, realm::Schema *schema);
|
|||
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
JSValueRef RJSPrototypeForClassName(const std::string &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.");
|
||||
|
||||
ObjectSchema objectSchema;
|
||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||
ObjectDefaults defaults;
|
||||
|
||||
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
|
||||
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
|
||||
|
||||
size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject);
|
||||
for (unsigned int p = 0; p < numProperties; p++) {
|
||||
JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p);
|
||||
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");
|
||||
JSValueRef primaryValue = RJSValidatedPropertyValue(ctx, objectSchemaObject, primaryString);
|
||||
|
@ -141,7 +155,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
|
|||
// store prototype
|
||||
if (prototypeObject) {
|
||||
JSValueProtect(ctx, prototypeObject);
|
||||
s_prototypes[objectSchema.name] = prototypeObject;
|
||||
s_prototypes[objectSchema.name] = std::move(prototypeObject);
|
||||
}
|
||||
|
||||
return objectSchema;
|
||||
|
@ -158,3 +172,4 @@ realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) {
|
|||
|
||||
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 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 long long to_long(ContextType ctx, ValueType &val);
|
||||
static float to_float(ContextType ctx, ValueType &val);
|
||||
|
@ -184,14 +187,18 @@ namespace realm {
|
|||
// populate
|
||||
Object object(realm, object_schema, table->get(row_index));
|
||||
for (Property &prop : object_schema.properties) {
|
||||
if (Accessor::dict_has_value_for_key(ctx, value, prop.name)) {
|
||||
if (created || !prop.is_primary) {
|
||||
ValueType prop_value = Accessor::dict_value_for_key(ctx, value, prop.name);
|
||||
object.set_property_value_impl(ctx, prop, prop_value, try_update);
|
||||
if (created || !prop.is_primary) {
|
||||
if (Accessor::dict_has_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);
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -86,7 +86,7 @@ var ObjectTests = {
|
|||
var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]});
|
||||
var obj = null;
|
||||
realm.write(function() {
|
||||
obj = realm.create('LinkTypesObject', [[1], undefined, [[3]]]);
|
||||
obj = realm.create('LinkTypesObject', [[1], null, [[3]]]);
|
||||
});
|
||||
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
||||
|
||||
|
@ -99,7 +99,7 @@ var ObjectTests = {
|
|||
TestCase.assertEqual(realm.objects('TestObject').length, 2);
|
||||
|
||||
realm.write(function() {
|
||||
obj.objectCol = undefined;
|
||||
obj.objectCol = null;
|
||||
obj.objectCol1 = 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() {
|
||||
var realm = new Realm({schema: [TestObjectSchema]});
|
||||
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