Reset a relation field to empty

We’re having trouble resetting a record’s column to no relations.
We have a table called Beacon, and it has a column named “messageUsersDelivered” that has a one-to-many relationship to Users.
We are saving that Beacon, and what to clear all the users in that column.
But are experiencing cases where sometimes when saving, the Users is not reset, and it still has the user relationships in it.
In iOS, what is the best way to save the beacon record to reset the column messageUsersDelivered to empty again.
Here is our current code :
//Set new message to beacon
beacon.message = _beaconMessage;
beacon.messageUsers = self.selectedRecipients;
beacon.messageUsersDelivered = [NSMutableArray new];
beacon.messageDate = [NSDate date];
beacon.messageIsFacebookPublish = self.beaconFbIsSelected;
beacon.messageIsPublic = self.beaconPublicIsSelected;

Beacon *updatedBeacon = [beacon save];
And then the “save” method on the beacon class:
-(Beacon *)save {
//Synchronous method
@try {
id<IDataStore> dataStore = [backendless.persistenceService of:[Beacon class]];
return [dataStore save:self];
}
@catch (Fault *fault) {
NSLog(@“beacon save FAULT: %@”, fault.message);
return nil;
}
}

Is the “beacon” object you’re saving received from the server or do you construct it in the app?

Its an object from the server.

From the “beacon” table.

What is the difference between “self” and “beacon” then here? Does “self” point to a object you got from the server too?

beacon.messageUsers = self.selectedRecipients;
beacon.messageUsersDelivered = [NSMutableArray new];
beacon.messageDate = [NSDate date];
beacon.messageIsFacebookPublish = self.beaconFbIsSelected;
beacon.messageIsPublic = self.beaconPublicIsSelected

ie, retrieved with the backendless datastore:

id <IDataStore> beaconStore = [backendless.persistenceService of:[Beacon class]];

Those are just properties on the current view.

ie, the updated data that is to be changed when saving the beacon record.

And our issue is that:
beacon.messageUsersDelivered is not being reset to no users when we save (in all cases).
It appears to work sometimes, others not.

Is there anything different between the requests when it works and when it does not? Perhaps requests that do not work result in a server error?

I’ve watched the responses.

And the strange thing is that the “save” method returns the updated object, as its a Synchronous method.
See " -(Beacon *)save " above.

And the result of that will show that the “messageUsersDelivered” is empty.
However, when I immediately open my browser, browse to that record, I can see that it in fact is not empty on the record. I refresh the data, and see its still not empty.

“messageUsersDelivered” is a one to many collection. When an object is being saved, the returned value will not contain the related objects, unless they are marked as “auto-load”. I would not use your observation as a way to determine if the relation had been broken or not. I will assign this to a developer to investigate the issue further.

Ok, thanks.

btw, it is set to “autoload”.

Internal ticket #: BKNDLSS-12464

Where can I see updates to this ticket?

it is still in progress, we will notify you when will be any update

Hi, Daniel!

I’ve tried to reproduce your issue, but without any success. Please try to find stable steps to reproduce this issue.
Here is a code sample I’ve tested with ( class Foo has one-to-many relation “users” with Users table ). Try to execute it:









    id&lt;IDataStore&gt; fooDataStore = [backendless.persistenceService of:[Foo class]];

    id&lt;IDataStore&gt; userDataStore = [backendless.persistenceService of:[BackendlessUser class]];

    

    NSMutableArray *initialArray = [ NSMutableArray new ];

    [initialArray addObject: [userDataStore findFirst]];

    [initialArray addObject: [userDataStore findLast]];

    

    NSMutableArray *emptyArray = [ NSMutableArray new ];




    Foo *foo = [ fooDataStore findFirst ];

    foo.users = initialArray;

    [fooDataStore save:foo];

    

    Foo *foundFoo = [fooDataStore findFirst];

    foundFoo.users = emptyArray;

    [ fooDataStore save:foundFoo ];

best regards,
Alex

Here you go, I’ve been able to confirm the bug using a modified version of your test:









-(void)testBackendlessSaveBug {

    

    id&lt;IDataStore&gt; fooDataStore = [backendless.persistenceService of:[Foo class]];

    id&lt;IDataStore&gt; secondFooDataStore = [backendless.persistenceService of:[Foo class]];

    id&lt;IDataStore&gt; userDataStore = [backendless.persistenceService of:[BackendlessUser class]];

    

    NSMutableArray *initialArray = [ NSMutableArray new ];

    [initialArray addObject: [userDataStore findFirst]];

    [initialArray addObject: [userDataStore findLast]];

    

    NSMutableArray *emptyArray = [ NSMutableArray new ];

    

    Foo *foo = [ fooDataStore findFirst ];

    foo.users = emptyArray;

    [fooDataStore save:foo];

    

    NSLog(@"1) Starting - foo usercount: %lu ", [foo.users count]);

    

    [NSThread sleepForTimeInterval: 1];




    //Simulate data changed by other device (by changing a second instance of the same Foo record)

    

    NSMutableArray *changeUsersArray = [ NSMutableArray new ];

    [changeUsersArray addObject: [userDataStore findFirst]];




    Foo *secondFoo = [ secondFooDataStore findFirst ];

    secondFoo.users = changeUsersArray;

    [ secondFooDataStore save:secondFoo ];

    

    NSLog(@"2) Simulating foo users being changed elsewhere (other device) - setting foo user count: %lu ", [secondFoo.users count]);

    

    [NSThread sleepForTimeInterval: 1];

    

    //Now save our first instance with an empty array

    foo.users = emptyArray;

    [ fooDataStore save:foo ];

    

    NSLog(@"3) Save and reset foo user count to 0 - foo usercount: %lu ", [foo.users count]);

    

    //Check our user count

    Foo *finalFoo = [fooDataStore findFirst];

    

    if ( [finalFoo.users count] > 0) {

        NSLog(@"Test result: Incorrect count - Foo user is not 0, count: %lu ", [finalFoo.users count]);

    } else {

        NSLog(@"Test result: Correct count - Foo user count is 0, count: %lu ", [finalFoo.users count]);

        NSLog(@"If correct, then if we run this test method one more time, usually it is incorrect the second time. Running again....");

        

        static dispatch_once_t onceToken;

        dispatch_once(&onceToken, ^{

            [self testBackendlessSaveBug];

        });

    }

}

Daniel, thank you for the code.

It works as expected. Let me explain.
This test would pass if and only if initial “foo” object has empty “users” property. Thats why this test fails every second run - after first run “foo” doesn’t have related users! Look what you have here:

  1. “foo” is retrieved, “users” property is empty
  2. You assign emptyArray as “users” for “foo” and save…
  3. …but server doesn’t change “foo” object, because it has been retrieved with empty “users”, and it has come back with empty “users”, and it doesn’t matter that it has been already changed.
    In order to prevent it you should retrieve the latest version of “foo” object right before changing it. I’ve added a line into your test. Now it should work well.








    NSLog(@"2) Simulating foo users being changed elsewhere (other device) - setting foo user count: %lu ", [secondFoo.users count]);

    

    [NSThread sleepForTimeInterval: 1];

    

    //Now save our first instance with an empty array

    

    foo = [ fooDataStore findFirst ]; // added line

    

    foo.users = emptyArray;

    

    [ fooDataStore save:foo ];

hope it helps,
Alex Navara

Hi Gus, I’m also need to clear (reset) my relation field.

My scenario is, I have a relation 1:n where Product has many ‘Ingredients’, these ingredients can be easily added or removed to/from a product. When a user has some ingredients and decides to remove all active ingredients I got an error, because now I have no ID to Set or Add. There is a way to just empty/reset the field?

Hi @MARCIO_PRUDENCIO,

have you checked this part of documentation?
Delete Objects from relation
I think it’s what you need here. Let me know if this does not work.

Regards,
Stanislaw

I did @stanislaw.grin and the documentation requests a child ID. When the user unselects all ingredients I have no child ID to set/add or remove. So this field can contain 5 related objects or none that is an option.

How can I reset a relation field back to none without passing any child IDs?

using the documentation examples I got an error:

“Child objects list not specified. Use either a whe…rray of childs with Content-Type application/json”

Also try to update as data field using an empty object and didn’t work either.