-
-
Notifications
You must be signed in to change notification settings - Fork 113
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
Fix for passing fragment arrays to fragments #364
base: master
Are you sure you want to change the base?
Fix for passing fragment arrays to fragments #364
Conversation
@@ -69,7 +69,7 @@ const StatefulArray = ArrayProxy.extend(Copyable, { | |||
|
|||
this._pendingData = data; | |||
|
|||
let processedData = this._normalizeData(makeArray(data)); | |||
let processedData = this._normalizeData(data instanceof StatefulArray ? copy(data) : makeArray(data)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@igorT added an instanceof check instead of using a specific property
|
||
order.products.firstObject.set('name', 'Wolfsbane'); | ||
assert.equal(order.products.firstObject.name, 'Wolfsbane', 'Modifies the original fragment array'); | ||
assert.equal(user.orders.firstObject.products.firstObject.name, 'Tears of Lys', 'It does not modify the passed fragment array'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@richgt @igorT so it appears this approach this means we lose a reference to the fragment array when we pass it in and copy it. See this test where I modify the original array to have the value 'Wolfsbane' but the value of the product within the user
model hasn't changed Tears of Lys
. Only the original is changed.
Digging into this a bit more, the difference between this and the old master
is that on these lines when we had a fragment array, we didn't call setupData
instead we just assigned it directly to the property. This meant we didn't call normalizeFragmentArray
.
With the recent refactor we are now always calling setupData
which means we are now normalizing the fragment array, even when it's already set up
To tell you the truth I'm not entirely sure what is the right behavior here but possibly in the spirit of the original code it should just do a simple assignment instead of re-setting up the data? I guess the original code suffered from the problem where the wrong owner is assigned to the fragmentArray?
if (serverFragment instanceof StatefulArray) {
serverFragment[name] = data.attributes[name];
} else {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@igorT @richgt I'm just wondering what's the best way to proceed here.
Solution 1
This PR in its current form.
- Does the
copy
but breaks backward compatibility - Loses the reference to the fragmentArray you passed in
- The owner is set up correctly through
setupData
Solution 2
- Don't re-call
serverFragment.setupData(data.attributes[name])
and instead just re-assign like we did pre-5.0. - Keeps the original reference to the fragment array
- Unfortunately the owner is now incorrect. The fragment array is still set to the initial owner. I’ve actually verified that this is existing behaviour pre-5.0 which to me seems like a bug.
Thinking about it my preference would be Solution 2, not requiring the copy
, and keeping the reference. Could we augment solution 2 with also resetting the owner to be the correct one? Should we even bother considering this “bug” already existed? Not having lots of context on the refactor what's the downside to not calling serverFragment.setupData(data.attributes[name]);
again.
Bringing this PR over from https://github.com/richgt/ember-data.model-fragments/pull/1 as I can't redirect the PR to a different repo.
@richgt @igorT This is a potential patch fix for the issue I mentioned I've been encountering with the
RecordData
refactor.The use case
I previously mentioned:
This issue is also causing us a lot of problems in how we bootstrap our tests as we use Factory Guy quite heavily. We'll do something like the following a lot where
make
will create our models and model fragments for us. In the following examplegrandparent.parent.children
is a fragment array.The problem
The specific problem appears to be that in current master when pass the
children
fragment array to the new model it doesn't try and normalize the fragment array a second time, but in the refactor it does. The error it throws is the following if you try to pass a fragmentArray to another model.It seems that when we are getting to this line
when trying to set up the FragmentArray, the
instance of
check innormalizeFragmentArray
assertion is throwing. This is even though we are trying to add the correct type of fragment to the fragment array.The fix
Digging in the actual problem is that rather than passing the Fragment Array directly to
normalizeFragmentArray
we are actually passing a Fragment Array wrapped in another array. This is due to the following line https://github.com/richgt/ember-data.model-fragments/blob/ab24b0fbd4870ac129ed634eb82181758b86524c/addon/array/stateful.js#L72. We aren't checking whether the passeddata
is already an array and are always wrapping it in one. My naive patch is to detect whether it's a fragment array and then copy it.