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

xhr@v2.3 compliance #77

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

dhritzkiv
Copy link
Member

@dhritzkiv dhritzkiv commented Nov 25, 2016

Recently, xhr clarified its behaviour for the json option, suggesting that json is flipped on/off, and the body is instead set to… the body. This has the side effect of preventing true/false being sent as a value via the json option, but is otherwise backwards compatible.

This PR is mostly to bring ampersand-sync inline with how xhr prefers its data, but also solves one very specific, confusing use case that would fail (without this PR). I'll try to explain it:

//get an ampersand-model somehow…
// and then proceed to create a custom request using `sync` (with a custom `body`),
// which basically proxies the options to xhr

const opts = {
    body: {foo: "bar"},
    json: true
};

model.sync("create", model, opts);

//what currently happens is ampersand-sync will set the `json` option 
// to the model's data (`model.toJSON()`), which will
// prevent `opts.body` from being used in `xhr`, as `json` contain the model's data,
// and since it's not a boolean, it takes precedence over `body`

//with this PR, ampersand-sync will now set `params.body` to the model's data.
// However, when it comes time to invoke `xhr`, `ajaxSettings` is
// built up of `params` and `options` (with the values in `options` taking precedence via `assign`).
// so, in the end the `body` property of `ajaxSettings` –which is what `xhr`will use in `send()`–
// is equal to `opts.body` (which is arguably what we want) and not the value from `model.toJSON()`

In short, this should make .sync options behaviour more congruent with xhr's options behaviour. While using body is not an option specified within ampersand-sync's documentation, and data should probably be the preferred way to pass data, sometimes it's tricky to remember which property to use (body or data) when switching between using xhr and ampersand-sync.

Overall, this PR shouldn't introduce any breaking changes.

xhr @v2.3 suggests that the `json` option should be a boolean, and the data should be set on `body`.

While the behaviour is backwards compatible, I figure it would be a good idea to match its behaviour.
…where the explicitly provided body should take precedence over the model’s data.
@@ -82,7 +83,7 @@ module.exports = function (xhr) {
// For older servers, emulate JSON by encoding the request into an HTML-form.
if (options.emulateJSON) {
params.headers['content-type'] = 'application/x-www-form-urlencoded';
params.body = params.json ? {model: params.json} : {};
params.body = params.json ? {model: params.body || params.json} : {};
Copy link
Contributor

Choose a reason for hiding this comment

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

Trying to think of the condition where params.json would be true, and there would be no params.body. This would result in params.body being set to {model: true} which seems incorrect.

If params.json is true, it means new lines 70 and 71 ran above, which means params.body has to be set to either options.attrs or model.toJSON(options). So at the bare minimum it's already set to {};

Following this logic I believe that this line should read:

params.body = params.json ? { model: params.body } : {};

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, you're right.

The case this was attempting to address was if somebody passed a non-boolean truthy value to json in options. Except now I realize this is json in params, which will always be (true || undefined).

Making this change shortly.

@wraithgar
Copy link
Contributor

This looks great, thanks for staying on top of this change. +1 from me

@naugtur
Copy link
Member

naugtur commented Nov 25, 2016

Great thinking, this could have been considered a bug before!
Travis seems broken because of missing credentials. If they're not there, how did it work before?

@dhritzkiv
Copy link
Member Author

@naugtur tests have been broken across all Ampersand modules for about a year now :(

I don't have the expertise or access to fix the CI tests.

@fyockm
Copy link
Member

fyockm commented Nov 26, 2016

👍

@wraithgar
Copy link
Contributor

Tests ran from PRs from external repos will always fail, only tests made from PRs from local branches will run.

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.

None yet

4 participants