How to pass variable while calling macros in post hook?

Viewed 92

Currently I am calling macros in such a way:

"post_hook":["{{macros_append('string1','string2')}}"]})}}

I want to call it as

"post_hook":["{{macros_append(var1,var2)}}"]})}}

I have already tried setting variable before config like

{% set var1='value' %}
"post_hook":["{{macros_append(var1,var2)}}"]})}}

But this does not work. It does not take any value while calling macros.

1 Answers

This doesn't work because dbt is parsing the jinja of your post-hook in a different context from the model file. In short, the post-hook needs to stand on its own.

This is true of all configs. The hints are:

  1. post_hook takes a list of strings. Those strings later get templated by the jinja templater. (this is why you quote them and nest the curlies! you should never really nest curlies otherwise)
  2. Configs can also get passed in through .yml files, etc., which is partially why the templating is deferred

Your question omits the actual call to the config macro, which makes this a little more clear:

{{
    config({
        "post_hook": ["{{macros_append('string1','string2')}}"]
    })
}}

So what are we to do? You could use jinja to build the string that gets passed into the config block. This is hacky and ugly, but it works:

(Note that ~ is the jinja string concatenation operator.)

{% set var1 = "string1" %}
{% set var2 = "string2" %}
{{
    config({
        "post_hook": ["{{ macros_append(" ~ var1 ~ "," ~ var2 ~ ") }}"]
    })
}}

A slightly cleaner version of this would be to define the whole macro call in a variable, so you don't have to do the concatenation:

{% set my_hook = "{{ macros_append('string1', 'string2') }}" %}
{{
    config({
        "post_hook": [my_hook]
    })
}}

A Better Way

Another option is to use the var() macro, which allows you to access a global variable in the jinja context. You define these global variables in your dbt_project.yml file:

...
vars:
  var1: string1
  var2: string2

and then you can access them with {{ var('var1') }} from any process that is templating jinja. In the case of your config block, that would look like:

{{
    config({
        "post_hook": ["{{ macros_append(var('var1'), var('var2')) }}"]
    })
}}

Note that the post-hook here is just a string that contains the string "var('var1')", but that's fine, since the templater will fill that in later, when the string is templated.

Related