typhonjs-backbone-parse / backbone-parse-es6

A fork of Backbone converting it to ES6 along with Parse 1.6+ integration and ES5 bundles.
Mozilla Public License 2.0
11 stars 0 forks source link

Serialization / Deserialization support for backbone-parse-es6 #5

Closed AlexisBarta closed 8 years ago

AlexisBarta commented 8 years ago

So I'm creating a relationship between an existing object post and a new object myComment like so:

'use strict';

import Backbone from "typhonjs/backbone-parse-es6";

export default class MIPost extends Backbone.Model
{
   /**
    * Returns the `className` which is the table stored in Parse.
    *
    * @returns {string}
    */
   get className() { return "MIPost"; }
}
'use strict';

import Backbone from "typhonjs/backbone-parse-es6";

export default class MIComment extends Backbone.Model
{
   /**
    * Returns the `className` which is the table stored in Parse.
    *
    * @returns {string}
    */
   get className() { return "MIComment"; }
}
var post = new MIPost();
post.id = "1zEcyElZ80";

var myComment = new MIComment();
myComment.set("parent", post);

When I'm run a mycComment.save(); the framework runs a batch trying to save post for no reason. I just want to create a relationship between myComment and post and saving myComment. Because after my CloudCode verification on Post objects throw me the error that my object attributes are empty...

I open the same issue on Parse repository: https://github.com/ParsePlatform/Parse-SDK-JS/issues/142

But apparently it's not the normal behavior.

typhonrt commented 8 years ago

I've been looking into this for the past couple of hours. The situation is that myComment.set("parent", post); is setting the Backbone.Model (IE ParseModel) to parent in the backing Parse.Object and this is what causes Parse to fail on save since the encode function doesn't know about ParseModel.

If you change myComment.set("parent", post); to myComment.set("parent", post.parseObject); then things work as far as saving myComment though of course that fouls things up with retrieving the ParseModel instead of Parse.Object with myComment.get("parent").

I've submitted an issue requesting a clean solution by having a replaceable encode function located in Parse.js which is used by ParseObject.js so that it can be replaced. Please see Parse-SDK-JS Issue #144.

Failing any cooperation from Parse I'm also experimenting with a more hacky / fragile solution. by modifying ParseModel.set() to set any parseObject field to the backing Parse.Object instead of the ParseModel and will also test that one can retrieve things correctly say in creation of a Collection for the MIPost table. More info on this in a follow up post in this issue.


Regarding your comment:

I just want to create a relationship between myComment and post and saving myComment. 
Because after my CloudCode verification on Post objects throw me the error that my 
object attributes are empty...

If you test with bare Parse:

import Parse   from 'parse';

const post = new Parse.Object('Issue5Post');

const comment = new Parse.Object('Issue5Comment');
comment.set('parent', post);

comment.save();

The post will be saved when comment is saved, so you're cloud code will still fail if it is verifying any post data. Also you can't even with using Parse directly successfully assign a random id to post when you save comment. Let Parse create the ID automatically.

typhonrt commented 8 years ago

@andrewimm I'd be glad to hear your ideas on how the Parse JS SDK can be improved to provide a clean solution to the above. Thanks.

AlexisBarta commented 8 years ago

When I'm doing this, it's working great (no CloudCode verification) :

var MIPost2 = Parse.Object.extend("MIPost");
var post = new MIPost2();
post.id = "1zEcyElZ80";

var comment = new MIComment();
comment.set("parent", post);
typhonrt commented 8 years ago

Yes, because you are assigning a Parse.Object to 'parent' and this works like I mentioned in my first post above. The trick is to transparently be able to assign a Backbone.Model (ParseModel) to comment->parent and have things just save a Parse pointer to the Parse.Object that is backing ParseModel when things are serialized.

Don't set the id when using backbone-parse-es6 / Backbone.Model. backbone-parse-es6 is not the same as Parse.

I'm still working on a fix and am kind of on to something, but we'll see. I really don't have much time to support backbone-parse-es6 since I'm moving on to other solutions.

AlexisBarta commented 8 years ago

I understood ;) I said that only because of your comment "The post will be saved when comment is saved, so you're cloud code will still fail [...]". But till we agree with each other.

I canb understand that you don' have much time, sorry for the extra work... It's working with the method provide above so I'm not in hurry.

typhonrt commented 8 years ago

No this is good to solve as it's a case that would have been discovered with a full test suite which will happen at some point. Almost there on the fix... :)

typhonrt commented 8 years ago

I have a solution, but as things go it requires a small modification to the Parse JS SDK to work. Since ParseObject->fromJSON is a static method this makes it hard to override this functionality to properly handle deserialization in the cleanest manner possible. I have a post on Issue #144 detailing the fix and am waiting for a response. It might be a while for the Parse SDK to get an update that allows a final fix to this issue.

typhonrt commented 8 years ago

So I have been able to solve this issue. For whatever reason I overlooked that ES6 static functions can still be overridden and in parseExtend.js I override the necessary methods of Parse.Object primarily fromJSON to deserialize / create a ParseModel / Backbone.Model.

There is a full test case: https://github.com/typhonjs-demos-test/typhonjs-issues-demos/tree/master/repos/backbone-parse-es6/src/issue5

and live example: http://js.demos.typhonrt.org/typhonjs-issues-demos/repos/backbone-parse-es6/src/issue5/index.html

It should be noted that there is now an additional getter method available for ParseModel / Backbone.Model get subClasses which should return an object hash of any associated Models referenced as pointers. The object hash requires keys to be className and values to be the Class (not instance!). By providing this hash Parse.Object.registerSubclass will be called for you.

Please see Issue 5 demo CommentModel for an example.

@AlexisBarta let me know if this solves your problem.