1

CloudKit JS offers methods to save, delete and fetch records but there is no easy methods to update en existing one. The documentation explains how to do it:

var query = {
    operationType : 'forceUpdate',
    recordType: 'List',
    record : {
        recordName : 'TheRecordIWannaUpdate',
        fields: { TheFieldToUpdate: { 'value': 42}}
    }
};
container.publicCloudDatabase.performQuery(query).then(function(response) {
    if(response.hasErrors) {
        console.log(response.errors[0]);
    } else {
        console.log('It's working')
    }
});

I tried this code and it returns It's workinghowever my record is not updated, what is wrong with this code?

Armand Grillet
  • 2,648
  • 2
  • 23
  • 50

2 Answers2

3

As the documentation states, update is the proper operationType to use in most situations.

update | Update an existing record. Only the fields you specify are changed.

It's always possible that the record was updated by another client between the time you read it and tried to apply new updates. The recordChangeTag is how the server knows which version you read, which is why the documentation states that you need to send it along in an update operation.

If operationType is update, set the recordChangeTag key to the value of the existing record [in the record dictionary].

When you try to update a record that was already updated by someone else, you will receive a conflict from the server because your recordChangeTag is old and you should handle that conflict in whatever way makes sense in your app. Maybe you want to tell the user and maybe you just want to merge the changes.

In special situations you might want to force the update to succeed. In that case, you can use the forceUpdate operationType, telling the server to ignore conflicts and take this update, and in this case you don't have to include the recordChangeTag.

forceUpdate | Update an existing record regardless of conflicts. Creates a record if it doesn’t exist.

If you use the normal update operationType and you receive a success (not a conflict) then the record should definitely be updated on the server. If it's not then something else is happening.

It is worth mentioning that you might find it more convenient to use the RecordsBatchBuilder when sending changes to the server. Here is an example of what you can do with it:

myDatabase.newRecordsBatchBuilder()
  .createOrUpdate(record1)
  .create(record2)
  .update(record3)
  .forceUpdate(record4)
  .delete(record5)
  .commit()

As you can see, it handles a lot of the options for you.

Dave Browning
  • 1,126
  • 6
  • 5
2

To update a record you can use the recordChangeTag. The latest recordChangeTag is needed.

Documentation

When you fetch a record from the server, you get the current version of that record as it exists on the server. However, at any time after you fetch a record, other users might save a newer version of the record to the server. Every time a record is saved, the server updates the record’s change token to a new value. When you save your instance of the record to the server, the server compares the token in your record with the token on the server. If the two tokens match, the server knows that you modified the latest version of the record and that your changes can be applied right away. If the two tokens do not match, the server applies the save policy your app specified to determine how to proceed.

Example

var record = {
    recordType: 'List',
    recordName: TheRecordIWannaUpdate,
    recordChangeTag: TheRecordTag,
    fields: {
      TheFieldToUpdate: {
        value: 42
      }
    }
};

The Save Policy does not work for me, but you can add it.

var options = {  
      zoneName: undefined,
      operationType : 'forceUpdate'
  };

container.publicCloudDatabase.saveRecord(record,options)
    .then(function(response) {
    if(response.hasErrors) {
        console.log(response.errors[0]);
    } else {
        console.log("It's working");
    }
 });
cxca
  • 46
  • 4