Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.Sign up
toJSON can discard relation if it has not been fetched with fetchRelated(relationName) #191
Given a toOne relation like this:
The problem seems to be the save() call. There the toJSON implementation of BackboneRelational expects the value (favorized in this case) to always be included in the superclasses return value for toJSON.
However it is
Thus the value for favorized_id is lost.
Here's some tests and the workaround we tried to apply to this problem.
I'm quite uncomfortable marking this as a patch as I do not understand the reationale behind this behavior of Backbone.Relational - I only understand that it is messing our app.
Here's my understanding:
This makes sense to me and makes it easy for my app to load minimal data from the server for each context a model might get displayed in.
Here's where it gets weird though: On re-serialization time (after some aspect of a model has been edited/ changed) toJSON does not contain any of the original data that was 'hidden' by Backbone.Relational.
And this reeks like a bug to me, because I would assume that the contract of toJSON is to always return the same thing that you used to create the object from. It certainly does in Backbone, and Backbone.Relational certainly changes this.
So what gives? Is this a bug in Backbone.Relational or not?
Here's some unit tests I used to isolate the problem:
And here's the workaround I applied:
What makes me uncomfortable mostly is that I am not sure what type of guarantees Backbone.Relational makes about keyContents and if it can just be used like this.
The actual bug seems to stem the toJSON implementation of Backbone.RelationalModel, where it does serialize collections, models and then just null, and is missing the case where it serializes the keyContents if it has not been loaded yet.
i'm not positive if your workaround will work properly in the cases where the relation/object is there. in those cases the id should show up already in the json, and you don't want to clobber it with keyContents if that's not correct.
my workaround (in toJSON) and yours solve some of the simple cases but definitely want to get @PaulUithol or @DouweM to help come up with a more comprehensive solution for this. would be nice to have access to the ID in both
@philfreo: yes, would be very welcome to have the heavyweights weight in - I've since refined that workaround to this:
Though it still dies when the last object of a to many relation has been removed in the app, because I haven't found the key to discerning that situation from a relation that has not yet been loaded. :-(
All right, I understand the problem you guys are running into, and I agree that we could handle this better.
How about the following setup:
I think this would cover all cases, such as still allowing us to destroy a relation with
I also agree it would be nice to keep
What do you think?
Thinking about this I'm pretty confident that this works for ToOne relations. However for ToMany relations I'm unsure if this works if you remove the last element of a ToMany relation.
Here's my understanding: If a ToMany relation is serialized to an empty array (with the current code) it is either not fetched or the last element of the relation has been removed. (This is derived from my problem definition, which is "Discern when a relation was fetched and when it was unfetched, so that the original key-content can be restored in toJSON on unfetched relations")
Under the rules laid out above, I'm not sure those could actually discern between those two situations?
Here's the problem table I used to think about this:
I see the following problem with ToOne relations, if the are null they can be either
The rules you mentioned above seem to cover this.
For ToMany relations I see a problem when they are empty, which means they are either
How is that covered from the rules you outlined above?
Additionally I would find it very helpful if the meta information if a relation was already fetched or not was exposed in the relation api somewhere. I'm thinking about an API that I can use to discern the three states involved here, i.e. was never fetched, fetch has started and fetch was completed. If I can bind events to this information that would allow me to give rich feedback to the user as to the status of the data fetch. Could be that this is actually something that needs to happen in Backbone itself, but at least Backbone.Relational should ensure that this information can be gathered in the meantime and is equaly availeable from to many relations and the objects contained therein.
The rules outlined above specify a difference between "unfetched-
That meta information about a relation being fetched is exactly that implementation I mention, I'll see if a public API for that is viable. Ideally, something like that would be part of Backbone itself, but for now we'll have to implement this ourselves.
Hahaha, I've got a GitHub email in my inbox saying there's a $100 bounty ;) But whatever the price, Monday is not going to work for me, seeing as I'm on holiday right now, due to be back on Monday. Anyone else who likes the sound of $50 is encouraged to have a crack at it though! Unfortunately, with work and school I'll have little time in the next couple of weeks.
Just to be clear, this issue is just about the