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

{?exists} and {^exists} now supports values from a promise #753

Merged

Conversation

samuelms1
Copy link
Contributor

I logged this as bug #752 - {?exists/} behavior different when using promises.

@sethkinast
Copy link
Contributor

sethkinast commented Nov 7, 2016

I think this won't quite be right because when you use await in this way, you'll be shifting the context of the body. This is very close, though.

I think something like this might fail with your change:

{
  a: {
    b: {
      test: Promise.resolve("BAD")
    },
    test: Promise.resolve("GOOD")
  }
}

{#a}{?b}{test}{/b}{/a}

For the test runner failure, it's because Node 0.10 doesn't have Promise-- use the "FalsePromise" constructor at the top of the test file.

@sethkinast
Copy link
Contributor

You probably want to use chunk.map similar to how Chunk#await does it, but you need to only check the truthiness of the body rather than delegating to Chunk#section, which is what await will do.

It hits this code:

if (bodies) {
  chunk = chunk.section(data, context, bodies);
} 

@samuelms1
Copy link
Contributor Author

@sethkinast thanks for the comments! I got pretty busy yesterday, so I had to switch over to other work. I'm going to take another look.

@sethkinast
Copy link
Contributor

Yep no rush! I appreciate you taking the time to work on a patch :)

Samuel Smith added 2 commits November 8, 2016 11:48
…ed {expected} to equal {actual}" rather than vice versa
…errors.

Previous implementation had an issue where the context was updated to the resolved promise data which was not intended as sethkinast pointed out.
@samuelms1
Copy link
Contributor Author

@sethkinast can you take another look? You are right that using Chunk#await resulted in the context changing to the value of the resolved promise which is not desirable. I think I have that addressed now, but let me know what you think.

@samuelms1 samuelms1 reopened this Nov 8, 2016
Copy link
Contributor

@sethkinast sethkinast left a comment

Choose a reason for hiding this comment

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

Looks good! A little change and then if you'll squash up your commits, I think we'll be ready to go

});
});
};

/**
* Render an error body if available
* @param thenable {Thenable} the target thenable to await
Copy link
Contributor

Choose a reason for hiding this comment

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

wrong param

* @param bodies {Object} may optionally contain an "error" which will be rendered
* @return {Chunk}
*/
Chunk.prototype.renderError = function(err, context, bodies) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice, good reusable func

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. Should I move it off of the Chunk object? When I added it originally I wasn't considering that I was updating a public api that's pretty well documented here: http://www.dustjs.com/docs/helper-api/

@@ -861,6 +861,17 @@
var body = bodies.block,
skip = bodies['else'];

if (dust.isThenable(elem)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you turn this into a little reusable func that we can use for exists and notexists both? Look above at getWithResolvedData as an example-- just a little helper func not attached to the Chunk prototype.

Copy link
Contributor

Choose a reason for hiding this comment

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

by "this" I meant the code inside the if() block that is

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code was definitely redundant between the two methods. I made a mapThenable method to address it.

…e used when also using a thenable.

The mapThenable function helps to resuse code in Chunk#await, Chunk#exists, and Chunk#notexists.  It was also updated to capture and log errors similar to how Chunk#map does (seems to be a desired behavior that was missing when using thenables).
Also fixed incorrect javadoc param on renderError(...).
@@ -725,6 +725,11 @@
return this;
};

Copy link
Contributor Author

@samuelms1 samuelms1 Nov 9, 2016

Choose a reason for hiding this comment

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

I added these docs straight from http://www.dustjs.com/docs/helper-api/. Looks like other docs are missing from some chunk methods that are on the helper-api page. I could add these if they aren't considered bloat. This Chunk#map method is great and the docs really made it's usage clear to me. As I was looking at making the code both smaller and resuable, it seemed apparent that what I really needed was a new map method for thenables, so I created the mapThenable(...) method. I'd like to put it on the Chunk object, but that would be altering the public API of that and I'm not sure that is desirable. I'm also wondering if I should move the Chunk#renderError method off of the Chunk prototype for the same reason or if it's simple, generic, and useful enough to keep.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you have the right separation. I think mapThenable is not something that a general public API would necessarily need, but renderError is nice. We can add it to the docs.

Samuel Smith added 2 commits November 9, 2016 00:27
Note that this does slightly alter behavior in that a log is always generated on error rather than the previous logic that would only log an error when an error body was not present.
@@ -861,6 +895,12 @@
var body = bodies.block,
skip = bodies['else'];

if (dust.isThenable(elem)) {
return mapThenable(this, elem, context, bodies, function(chunk, data){
Copy link
Contributor

Choose a reason for hiding this comment

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

Fantastic. Style nit: space between function(chunk, data) and its brace

@sethkinast
Copy link
Contributor

Great work! If I can hassle you to fix the brace nit (which I should add to the linter...) we're ready to roll.

Also shoutout for writing great function documentation.

dust.log('Unhandled stream error in `' + context.getTemplateName() + '`', INFO);
}
chunk.renderError(err, context, bodies);
dust.log('Unhandled stream error in `' + context.getTemplateName() + '`', INFO);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that this is a logic difference. Previously dust.log(...) was only called when there was no render body whereas now it is always logged. I think it's ok.

@sethkinast sethkinast merged commit d485a72 into linkedin:master Nov 9, 2016
@sethkinast
Copy link
Contributor

Thanks again for the PR! 🎆

@samuelms1
Copy link
Contributor Author

@sethkinast it was my pleasure. It was a lot of fun. Makes me want to contribute more in open source projects.

What is the release cycle for these changes? I'd like to start using them as soon as they become available.

@sethkinast
Copy link
Contributor

I'm tempted to cut a 2.8, which I didn't plan on before a 3, and spend 3.0 working on an ES6 rewrite.

You could use the changes today by putting a commit hash in your package.json instead of a version number, if you wanted.

@samuelms1
Copy link
Contributor Author

@sethkinast We don't reference dustjs-linkedin directly or I might consider that. We use hoffman for the expressjs integration it provides. hoffman uses duster and duster uses dustjs-linkedin.

The ES6 rewrite sounds like a fun project to work on. Is there a branch for it?

@sethkinast
Copy link
Contributor

I have not pushed a public branch for ES6 yet but hopefully soon.

Let me see about cutting a 2.8 in the next week or two.

@samuelms1 samuelms1 deleted the exists-supports-promised-values branch April 20, 2017 18:30
@samuelms1 samuelms1 mentioned this pull request Sep 13, 2017
5 tasks
jrrbru pushed a commit to jrrbru/dustjs that referenced this pull request Nov 25, 2019
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.

2 participants