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

normalizeErrors with nested errors breaks for polymorphic associations #3017

Closed

Conversation

jbourassa
Copy link

Calling normalizeRelationships from normalizeErrors breaks for polymorphic relationships in ActiveModelSerializer (introduced in #2392, see this diff). Here's a failing test.

This happens because ActiveModelSerializer's normalizeRelationships will inspect the payload for a type property. Since this is an error payload, the type property won't be set. Here's the (albeit not so pretty) workaround we have:

{
  // stuff...
  normalizeErrors: function(type, hash) {
    this.normalizeId(hash);
    this.normalizeAttributes(type, hash);

    if (this.keyForRelationship) {
      type.eachRelationship(function(key, relationship) {
        var payloadKey = this.keyForRelationship(key, relationship.kind);
        if (key !== payloadKey && hash.hasOwnProperty(payloadKey)) {
          hash[key] = hash[payloadKey];
          delete hash[payloadKey];
        }

        if(!hash || !hash[key]) return;
        // Array.isArray => basically checking for .kind === 'hasMany'
        if(Array.isArray(hash[key])) {
          hash[key].forEach(function(hash) {
            if(hash) this.normalizeErrors(relationship.type, hash);
          }.bind(this))
        }
        else {
          this.normalizeErrors(relationship.type, hash[key]);
        }
      }, this);
    }
  }
}

Would you like me to improve this code and submit a PR?

@bmac
Copy link
Member

bmac commented May 6, 2015

@jbourassa thanks for the workaround and test case. Would you like to open a pull request to fix this issue?

@jbourassa
Copy link
Author

Would you like me to improve this code and submit a PR?

Would you like to open a pull request to fix this issue?

Absolutely! Will do in the next few days.

@jbourassa
Copy link
Author

Hey @bmac,

I just updated the issue with a PR. Let me know what you think!

}
if (relationship.kind === 'hasMany' && isArray(hash[key])) {
forEach.call(hash[key], function(hash) {
if (hash) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hash as an argument name is a little confusing because there already is a hash argument from the parent scope. Lets rename this to something else. Maybe error?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! I used errors since any key can hold multiple errors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good.

@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch from 05d7b15 to 6f8ede2 Compare May 11, 2015 15:42
var serializer = env.container.lookup('serializer:application');
serializer.extractErrors(env.store, MediocreVillain, payload, null); // id (last param) is not relevant here

ok(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test should assert that the record error object was extracted correctly. It might look something like:

var extractedError = serializer.extractErrors(env.store, MediocreVillain, payload, null); // id (last param) is not relevant here

deepEqual(extractedError, {
  evilMinions: [{ name: ['required'] }]
});

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also very correct, my bad. I didn't look very far and kept my original test that was flat out erroring. That is also fixed!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it's a bit more complicated than that. The serializer will not change the key from evil_minion to evilMinions because it is looking for evil_minion_ids.

So there are two things that are relevant in this test:

  1. No matter what you pass in, extractErrors should crash (eg: not look for a .type property on an error payload)
  2. If the serializer is configured to rename the evil_minions association to evilMinions, errors should also be renamed.

I updated the test again to cover (2), but I had to bring in EmbeddedRecord.

@bmac
Copy link
Member

bmac commented May 11, 2015

@igorT @tchak Does Ember Data's Error handling mechanism handle the case were the error object for a hasMany relationship be an array of error objects or do these errors get silently ignored? e.g.

{
    errors: {
      evil_minions: [
        { name: ['required'] },
        { name: ['required'] }
      ]
}

@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch from 6f8ede2 to a7d9dcd Compare May 11, 2015 16:13
@jbourassa
Copy link
Author

@bmac

Does Ember Data's Error handling mechanism handle the case were the error object for a hasMany relationship be an array of error objects or do these errors get silently ignored? [...]

I know you didn't ask me — I have no idea if support is intended or not — but it works and we do use it in our app, keeping it would be very nice 🙏

@bmac
Copy link
Member

bmac commented May 11, 2015

Sorry @jbourassa that question was meant to be directed at @igorT. I posted it to this issue to give him some context.

@jbourassa
Copy link
Author

The tests were passing locally but not from a fresh install: I'll investigate.

@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch from a7d9dcd to 77201a8 Compare May 11, 2015 21:09
if (key !== payloadKey && hash.hasOwnProperty(payloadKey)) {
hash[key] = hash[payloadKey];
delete hash[payloadKey];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since #3040 the normalizeUsingDeclaredMapping method is invoked inside normalizeErrors: this makes the above lines 293-297 obsolete as the hash already contains the normalized relationship keys. The call for this.normalizeRelationshipErrors inside normalizeErrors above needs to moved up though, so this works correctly.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something but I don't think that's correct. normalizeUsingDeclaredMapping only normalize declared keys, not association defaults defined with keyForRelationship.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! You're right, I haven't thought about keyForRelationship 👍

@jbourassa
Copy link
Author

@pangratz Thanks for the feedback / sorry for not nailing it better. This is taking longer than I want but I'll update the PR at some point this week.

@pangratz
Copy link
Member

sorry for not nailing it better

@jbourassa I hope I didn't leave the impression you need to apologize and if so I am very sorry! That was absolutely not my intention 😟 . I am very happy you took the time and effort to add this to the core of ember-data. I am using a quite similar implementation within an app but never had the time to submit a patch. Once this lands I can remove that bit 👯

Feel free to ping me if you want further feedback or need anything else. Cheers!

@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch 2 times, most recently from 4b80f2f to 169422a Compare May 29, 2015 18:31
@tchak
Copy link
Member

tchak commented Jun 9, 2015

We are moving internal representation of errors to a son-api format. It means there is no such thing as nested errors or nested relationships on internal representation. We are going to need to normalize to something flat with the right pointer.

Something like ?

{
  "errors": [
    {
      "title": "required",
      "source": { "pointer": "included/3/attributes/name" }
    }
  ]
}

@jbourassa
Copy link
Author

Got it! We're not transitioning our errors to json-api in in the next few weeks so I'll go ahead and close this PR.

@jbourassa jbourassa closed this Jun 10, 2015
@igorT
Copy link
Member

igorT commented Jun 10, 2015

@jbourassa why close if you are not transitioning, this is still a bug we should fix?

@jbourassa
Copy link
Author

@igorT Well, would you rather me to reopen and revert the last commit that handles nested relationships? If I understand correctly, this code and the original bug will be obsolete when json-api errors are implemented, so I don't see why you'd want to merge this.

@igorT
Copy link
Member

igorT commented Jun 10, 2015

we still want the failing test though?

@jbourassa
Copy link
Author

I might be missing something but if ember-data drops support for non-json-api error payload, the failing test will also be irrelevant, no?

@igorT
Copy link
Member

igorT commented Jun 10, 2015

We are switching our internal error format to json api, but active model serializer should still work.

@jbourassa
Copy link
Author

Gotcha! I'll reopen and leave the failing test.

@jbourassa jbourassa reopened this Jun 10, 2015
@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch from 169422a to 005a244 Compare June 10, 2015 03:48
@jbourassa jbourassa force-pushed the errors-polymorphic-relationships branch from 005a244 to 393fbf8 Compare June 10, 2015 04:15
@jbourassa
Copy link
Author

Done — I forced-push an updated test and rebased it on master.

@fivetanley
Copy link
Member

@jbourassa Sorry for the late follow-up. Can you update the PR or close it if it's no longer needed?

@jbourassa
Copy link
Author

This is still an issue with 1.13 (the version I'm on), but I think it's gone in 2.3 — I can't find the offending code in master. That said, I feel that this use case is pretty far from where ember data is going with JSON API, I don't think it's a bug at this point but just something that is not supported.

Let's close this.

@jbourassa jbourassa closed this Jan 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants