Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom objectId before saving #99

Closed
lsmilek1 opened this issue Mar 20, 2021 · 14 comments · Fixed by #100 or #101
Closed

Custom objectId before saving #99

lsmilek1 opened this issue Mar 20, 2021 · 14 comments · Fixed by #100 or #101
Labels
type:feature New feature or improvement of existing feature

Comments

@lsmilek1
Copy link
Contributor

Hello,

is there a way how to set custom objectId before the object gets saved into Parse? This does not need to be for user login/sign-up, bot than later for other objects. The reason is that I am allowing user to save objects locally in the app (Realm) before they need or are synced with server, so the Id is already defined.

After login the user I tried following object:

`struct TestParseObject: ParseObject {

var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var itemName: String?

}`

saving with this code:

static func testSave() { var testObject = TestParseObject() testObject.itemName = "Able" testObject.objectId = "EaGax1Mnym" testObject.save { (result) in print("save result: \(result)") } }

result is:
save result: failure(ParseSwift.ParseError(code: ParseSwift.ParseError.Code.objectNotFound, message: "Object not found."))

If I do not change objectId, the object saves successfully.

Workaround would be to add one more field and save the other Id in that separate field, but that feels like unnecessary traffic and server load. In the custom server setting I was able to set:

{ "allowCustomObjectId": true }

And I noticed through the community that above functionality should be possible. Looking into the code description I see that there might be some wrong password also:

/** Object doesn't exist, or has an incorrect password. */ case objectNotFound = 101

But the password reference is only for user object, right?

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 20, 2021

Parse-Swift current doesn't support this. If was briefly mentioned in the forums: https://community.parseplatform.org/t/cant-fetch-objects-with-pointers/1471/5?u=cbaker6

It looks like the JS SDK implemented this here: parse-community/Parse-SDK-JS#1309. My guess is the process is similar to adding it to this SDK. If you would like to open a PR and add the functionality, I can review it.

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 20, 2021

Workaround would be to add one more field and save the other Id in that separate field, but that feels like unnecessary traffic and server load.

I personally have a situation like this, but I just create another field called uuid (basically whatever the name of the field is in the local database). I don't cross these over when syncing to the Parse Server, I just either query for objectId or uuid.

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 20, 2021

This actually seems pretty easy to add to the SDK, I’ll see if I can find some time later on today to add it

@cbaker6 cbaker6 mentioned this issue Mar 21, 2021
5 tasks
@lsmilek1
Copy link
Contributor Author

Great! Let me know how can I buy you a coffee!

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 21, 2021

And I noticed through the community that above functionality should be possible. Looking into the code description I see that there might be some wrong password also:
/** Object doesn't exist, or has an incorrect password. */ case objectNotFound = 101

Someone from the server team might have to chime (@dplewis do you have some insight?) in about this particular error. My guess is from the message, it's kind of broad and covers a few different types. Maybe after the PR you won't receive this error anymore.

Great! Let me know how can I buy you a coffee!

Thanks for offering, I never had this setup before, but just added it to my GitHub profile.

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 22, 2021

@lsmilek1 just released 1.2.2 with the ability to add custom objectIds. Let us know if it works out for you.

@lsmilek1
Copy link
Contributor Author

lsmilek1 commented Mar 22, 2021

Hi, I am trying it now, but I might be missing some point again unfortunately. I added parameter in the init function in thedidFinishLaunchingWithOptions function:

ParseSwift.initialize(applicationId: "...", clientKey: "...", serverURL: URL(string: "https://...")!, allowCustomObjectId: true)

in the first controllers viewDidLoad I print successfully the current user:

Optional(_User ({"createdAt":{"__type":"Date","iso":"2021-03-21T17:55:01.092Z"},"username":"hoho","objectId":"Zf47seCdcD"}))

and after I try to run following on the same test object as the first post:

static func testSave() { var testObject = TestParseObject() testObject.itemName = "Able2" testObject.objectId = "EaGax1M111" testObject.save { (result) in print("save result: \(result)") } }

the result is a bit longer description:

Failure(ParseSwift.ParseError(code: ParseSwift.ParseError.Code.unknownError, message: "Error decoding parse-server response: Optional(<NSHTTPURLResponse: 0x7fce7d530760> { .... _long description_ ... with error: The data couldn’t be read because it is missing. Format: Optional(\"{\\\"message\\\":\\\"Not Found\\\",\\\"error\\\":{}}\")"))

I double-checked and I have "allowCustomObjectId": true in the Custom Parse Server Options. Did I miss to set any other parameter somewhere to get it working or do I simply set the objectId at wrong place/time?

@cbaker6 cbaker6 reopened this Mar 22, 2021
@cbaker6
Copy link
Contributor

cbaker6 commented Mar 22, 2021

in the first controllers viewDidLoad I print successfully the current user:
Optional(_User ({"createdAt":{"__type":"Date","iso":"2021-03-21T17:55:01.092Z"},"username":"hoho","objectId":"Zf47seCdcD"}))

Does this mean you were able to save your user with a custom objectId?

@lsmilek1
Copy link
Contributor Author

User I did not tried to save with custom Id as this is not required by the app architecture. The user I created and logged in yesterday already

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 22, 2021

I double-checked and I have "allowCustomObjectId": true in the Custom Parse Server Options. Did I miss to set any other parameter somewhere to get it working or do I simply set the objectId at wrong place/time?

Setting allowCustomObjectId on the server and in the SDK are the only places I believe you need to set. Did you restart your server after changing the setting?

@dplewis do you have any insight on this? Let me know if I misinterpreted something in the save/update testcases:

func testSaveCommand() throws {
let objectId = "yarr"
var score = GameScore(score: 10)
score.objectId = objectId
let className = score.className
let command = score.saveCommand()
XCTAssertNotNil(command)
XCTAssertEqual(command.path.urlComponent, "/classes/\(className)/\(objectId)")
XCTAssertEqual(command.method, API.Method.POST)
XCTAssertNil(command.params)
XCTAssertNotNil(command.data)
guard let body = command.body else {
XCTFail("Should be able to unwrap")
return
}
let expected = "{\"score\":10,\"player\":\"Jen\",\"objectId\":\"yarr\"}"
let encoded = try ParseCoding.parseEncoder()
.encode(body, collectChildren: false,
objectsSavedBeforeThisOne: nil,
filesSavedBeforeThisOne: nil).encoded
let decoded = try XCTUnwrap(String(data: encoded, encoding: .utf8))
XCTAssertEqual(decoded, expected)
}
func testUpdateCommand() throws {
var score = GameScore(score: 10)
let className = score.className
let objectId = "yarr"
score.objectId = objectId
score.createdAt = Date()
score.updatedAt = score.createdAt
let command = score.saveCommand()
XCTAssertNotNil(command)
XCTAssertEqual(command.path.urlComponent, "/classes/\(className)/\(objectId)")
XCTAssertEqual(command.method, API.Method.PUT)
XCTAssertNil(command.params)
XCTAssertNotNil(command.data)
guard let body = command.body else {
XCTFail("Should be able to unwrap")
return
}
let expected = "{\"score\":10,\"player\":\"Jen\",\"objectId\":\"yarr\"}"
let encoded = try ParseCoding.parseEncoder()
.encode(body, collectChildren: false,
objectsSavedBeforeThisOne: nil,
filesSavedBeforeThisOne: nil).encoded
let decoded = try XCTUnwrap(String(data: encoded, encoding: .utf8))
XCTAssertEqual(decoded, expected)
}

@lsmilek1
Copy link
Contributor Author

In the Back4App dashboard I went to Server Settings --> Core Setting --> Restart App now and seems to not have any effect. I also did clean and build the project in Xcode with the updated SPM library, I forgot to mention in previous post

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 27, 2021

@lsmilek1 the problem was how I implemented this in ParseSwift. I've added a fix and tested it on an actual server in #101 and released it in version 1.2.3

@cbaker6 cbaker6 mentioned this issue Mar 27, 2021
3 tasks
@lsmilek1
Copy link
Contributor Author

I can confirm this is working now. Thank you for your support!

@cbaker6
Copy link
Contributor

cbaker6 commented Mar 28, 2021

Awesome! Let us know if you run into any other issues

@cbaker6 cbaker6 closed this as completed Mar 28, 2021
@mtrezza mtrezza added type:feature New feature or improvement of existing feature and removed type:improvement labels Dec 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:feature New feature or improvement of existing feature
Projects
None yet
3 participants