How to represent flexible data models in Core Data? - ios

I'm quite new to the world of data persistence and Core Data and I have a hard time representing a model for my app.
My app is a collection of forms and will feature a "template editor" that allows the user to choose what fields should these forms contain. For example, an user might want to create forms with the fields "name", "age" and "picture". Those three attributes can all be of different types (String, Int, and Data). Moreover, there's no guarantee what the user will select. They could add 45 different fields including custom ones (with their own titles) if they wanted.
My question is what would be an efficient way to model one of these forms in Core Data?
I thought about representing every attribute in the model, or making a dictionary attribute with all the fields… But since I'm a beginner, I'm afraid of making a wrong technical choice that could hurt the app's efficiency or ability to execute predicates, etc.
Thank you in advance 🙂

Since user can add n number of fields in a template, adding every fields into the DB is not good idea. This will lead to a big size and this will volute the db normalisation.
Better to convert the template into single json which can be stored in a file based on template name or id. If you have a DB already then you can link the file name into a user object. Same json can be used to upload to server or render the template again from the same json file.
Even you can position the fields based on id else even you can added position field in the json in order to maintain the field orders.
Example:
{
"template_id": "xyz",
"fields": {
"textfield": [
{
"label": "First Name",
"value": "Stack",
"id": 1
},
{
"label": "Last Name",
"value": "Overflow",
"id": 2
}
],
"image": [
{
"label": "Profile Photo",
"value": "/Document/Images/Profile.jpeg",
"id": 3
}
],
"date_picker": [
{
"label": "DOB",
"value": "01/01/1980",
"id": 4
}
]
}
}

Why not use this simple design for your models?. Here they are represented as structs but they are easily translated to entities
struct Form {
var name: String
var fields: [Field]
}
struct Field {
var name: String
var type: String //Maybe an enum in code
//var form: Form :in a struct you don't have this property but your entity will have it as a relationship
}

I believe dictionary model is best for this because you don't know what n how many fields user is going to use. But you can save those fields values in to string type and store it in ur core data.

Use Microsoft Excel to prototype and design a database. Once it's done, create your CoreData model.

Related

How do I use $expand on ownerid to fetch SystemUser properties with the Dynamics 365 Web API?

I'm using Postman to query the Dynamics 365 Web API to fetch Account records. I'm trying to use expand to fetch some properties from the related SystemUser record via the ownerid field.
Here is what I think the query should look like:
https://myorg.api.crm4.dynamics.com/api/data/v9.0/accounts?$select=name&$expand=ownerid($select=fullname)
When I submit this query I get the error:
Could not find a property named 'fullname' on type 'Microsoft.Dynamics.CRM.principal
I know that the fullname property definitely exists on a SystemUser.
If I remove the ($select=fullname) part of the query I get the following JSON result but I was expect lots of properties for the expanded owner.
{
"#odata.context": "https://myorg.api.crm4.dynamics.com/api/data/v9.0/$metadata#accounts(name,ownerid)",
"value": [
{
"#odata.etag": "W/\"1564360\"",
"name": "My Account",
"accountid": "82b287d6-0dc7-e811-a95e-000d3ab1ab19",
"ownerid": {
"ownerid": "5f8872b1-0189-e811-a975-000d3ab38ab1"
}
}
]
}
If I change the expand to use primarycontactid then this works and I can fetch fields from a Contact record.
I've checked the documentation and I'm no further forward.
https://learn.microsoft.com/en-us/dynamics365/customer-engagement/developer/webapi/query-data-web-api
How do I use expand to fetch properties from a SystemUser record via the ownerid property of Accounts?
It looks like the issue is due to the Owner field being able to point at either a SystemUser or Team record.
If I expand with owninguser then I can fetch the correct properties from the related Systemuser.
/api/data/v9.2/new_customs?$select=createdon,_ownerid_value&$expand=owninguser($select=fullname)&$filter=(owninguser/systemuserid%20ne%20null)&$top=50

userType field - which values are allowed?

Microsoft Graph API's User entity has field "userType". According to documentation there is no any information about this. There is one line: "A string value that can be used to classify user types in your directory, such as “Member” and “Guest”. Supports $filter.". So there is no any limitations :-)
Can be "userType" null? I can't PATCH existing user manually via graph api - graph api return an error. But on production we have some users, which have "userType": null
Which values are valid for "userType"? Can you provide it in documentation or here please?
According to your questions, I suppose you want to know the valid value of the field userType. we can refer to the content of User Entity.
For your first question, we can set the field userType to null, not " " or "null". When we create a user, the default value of this field will be Member if we didn't set it.
We can patch existing user. Based on my test, we can modify it like this:
PATCH https://graph.microsoft.com/v1.0/users/{userid}
{
"displayName": "XXX",
"givenName": "XXXX",
"jobTitle": "Marketing Director",
"userType": "Guest"
}
This will modify the user'userType from Member to Guest.
For your second question, according to the content of User Entity and the article of Azure AD User, the valid value for userType is "Member" and "Guest". Based on my test, it is sure that only these two values can be used.

How do I prevent child properties from being updated?

When I use RestfulController in Grails to save data for an object, how can I prevent the client from applying changes to a related child object?
Given the following domain classes:
class Language {
String name
}
class TranslationText {
Language language
String text
}
And the following POST data for a TranslationText:
{
"language": { "id": 1, "name": "InvalidName" },
"text": "Some Text"
}
Here, I want to reference an existing Language resource (with ID=1), but I don't want the name to be altered by the client.
How can I save this resource with the text and language (based on ID), but discard the invalid language name property?
I want to modify RestfulController in the most minimal way possible, preserving default behavior as much as I can.
I think you need to configure the 'cascade' mapping property. This will tell GORM to evict the linked instance, so it won't be in the Hibernate session, changed to a new name and flushed to the DB :
class TranslationText {
Language language
String text
static mapping = {
language cascade: 'evict'
}
}
ref : http://docs.grails.org/3.1.x/ref/Database%20Mapping/cascade.html

Flatten request mapping hierarchy in RestKit

With RestKit, I'm trying to create a request mapping that would convert a payment object into JSON. This object stores sub-payments, of which only one is valid. This valid payment is represented by the property selectedPayment. I think the typical approach for this is to use a relationship mapping however I don't want the selectedPayment to appear as a nested key. An example of the result of my current approach is below:
{
"requestUserId" : "6",
"payment" : {
"selectedPayment" : {
"amount" : "5",
"id" : 70,
"type" : "SOME_TYPE"
}
}
}
My desired output is the following:
{
"requestUserId" : "6",
"payment" : {
"amount" : "5",
"id" : 70,
"type" : "SOME_TYPE"
}
}
I have tried numerous options for my relationship mapping's destination key path: #root, #parent, "", nil. All of which have resulted in a crash (except "", which nests the selected payment under an empty key).
I could modify the attribute mappings of the request mapping that is used for selectedPayment to explicitly use #root or #parent but this would not be ideal as it would negatively affect other areas that mapping is used.
This seems like typical behaviour, converting a "deep" object representation into a "shallow" JSON representation, surely there is a straightforward way to do it?
Instead of using a relationship mapping, use key paths in your single mapping, navigate into the property and then extract the keys that you seeking.
Don't use a relationship mapping, instead use key paths in your single mapping to navigate into the property and extract the keys you want. So you would use selectedPayment.amount, selectedPayment.id and selectedPayment.type as the source key paths in the mapping and amount, id and type As the respective destination keys.

RestKit object mapping with foreign keys and services

I am trying to set up a RestKit object mapping for a rest-like service over what I unfortunately have no control.
The model is a wish list with with a list of products. The WishList and the Product has obviously many-to-many relation. The wish list and the product has various attributes, for simplicity let's suppose that they both have only name.
I have separate services to get the details a wish list, the details of the product, and the relationship between them.
For example:
GET /api/wish_list/?id=1234
{
"name"="My wish list",
"id"=1234
}
GET /api/products
{
products:[
{
"name"="Product 1",
"id"=1111
},
{
"name"="Product 2",
"id"=2222
},
{
"name"="Product 3",
"id"=3333
}]
}
GET /api/wish_list_products/?wish_list_id=1234
{
products:[
{
"id"=1111
},
{
"id"=2222
}
}
I created the core data relationship between the Product and WishList entities but how could I tell to RestKit the fact that it should make a second request to fetch the list of the IDs of the products for a particular WishList?
I guess I should use [RKRoute routeWithRelationshipName:objectClass:pathPattern:method:] and/or RKConnectionDescription object, but I really could not figure out from the help how they could help me in my case.
RestKit won't automatically load the data for the relationship, you need to tell it when to do so. If you add the route using routeWithRelationshipName:objectClass:pathPattern:method: then you can make the request using getObjectsAtPathForRelationship:ofObject:parameters:success:failure:. Basically it makes linking the relationship name to the request to gather the required details.

Resources