Skip to content

explode when variables are undefined #207

Closed
jric opened this Issue Mar 14, 2013 · 4 comments

3 participants

@jric
jric commented Mar 14, 2013

It is mentioned in the Swig documentation that an undefined variable will not "blow up" your Javascript, but just be replaced with an empty value. That's good for templates that are being rendered to your customers, but how about:

  1. As a developer, you may not notice that a value is missing. You want to be alerted when your template is trying to access a value that is not defined, e.g. in the console.
  2. In a backend-script, a missing variable is an indication of a serious problem. You always want to be notified.

We can achieve this behavior by creating a custom filter which will throw an exception for an undefined value, and then explicitly use this filter for every variable instance. This wouldn't be very fun.

Is there a way to configure Swig to tell it, whenever you try to access a non-existent variable, I want you to explode? Failing that, is there a way to apply a custom filter to every instance of a variable access, without explicitly doing it for each?

@paularmstrong
Owner

This would require a very heavy rewrite.

You're better off writing unit tests for the output from your controllers/models.

@jric
jric commented Mar 18, 2013

Ah, ok. That is the workaround I ended up using. I wrote a function like this, which I run against anything I pass to the Swig template rendering function:

var assertAllPropsNotNull = function (obj) {
    for (prop in obj) {
        if (obj[prop] === undefined) {
            throw Error("property is not defined: " + prop);
        }
        if (obj[prop] === null) {
            throw Error("property is null: " + prop);
        }
    }
};
@jric
jric commented Mar 20, 2013

Oh, but you're right, in order to catch cases where I've misspelled a variable name, I'd need to test the output. Of course, this is not necessarily easy, and in case I don't want to write unit tests for the presence of every variable substitution, I guess I'm outta luck.

@popec
popec commented May 31, 2013

I've made simple tag that throws exception if some of passed variable or attribute is missing.

var helpers = require('swig/lib/helpers');

module.exports = function (indent, parser) {
    var output = [];
    output.push('var missing = [];');
    for (var key in this.args) {
        var arg = this.args[key].trim();
        if (arg.length === 0) continue;
        output.push('if (' + (helpers.check(arg, '_context')) + ' === false) { missing.push("' + arg + '"); }');
    }
    output.push('if (missing.length > 0) { throw "ERROR: Missing template variables: " + missing.join(","); }');
    output.push(parser.compile.call(this, indent));
    return output.join('');
};

module.exports.ends = true;

To use it put it in somewhere in template:

{% rq variable.attribute1 variable.attribute2 nextVariable
      moreVariables.length
  %}{% endrq %}

Allow Errors in Swig init and add custom tag:

swig.init({
    allowErrors: true,
    tags: require(__dirname + 'YOUR_PATH_TO_CUSTOM_TAGS')
});

And just catch error on render

try {
    var body = swig.compileFile(template).render(data);
} catch (e) {
   console.log('GotYa!');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.