Search code examples
jinja2dbt

How to dynamically call dbt macros using jinja?


I have a use case where I would like to define the name of a macro and then apply it to one column.

A simplified example could be as follows. I have two macros defined that I want to call dynamically in my model (both take one column as an input):

  • cast_to_string
  • convert_empty_string_to_null_value

Now, I want to call them dynamically. See the example below

{%- set macro_names = ["cast_to_string", "convert_empty_string_to_null_value"] -%}

select
    {% for macro_name in macro_names %} 
        -- this should dynamically be evaluated to `{{ cast_to_string(my_column) }}`
        -- and `{{ convert_empty_string_to_null_value(my_column) }}`
        {{ macro_name(my_column) }} 
    {% endfor %}
from my_model

However, this will throw an error saying that a string is not callable. I also tried using {% raw %} {{ {% endraw %} to escape brackets, but that didn’t work either.

So, my question is, if there is a way to dynamically call macros in jinja/dbt?


Solution

  • I think it should work if you remove the quotes :
    {%- set macro_names = [cast_to_string, convert_empty_string_to_null_value] -%}

    So that jinja doesn't interpret it as string and you can use it as a Callable

    I achieve it using this example :

    {%- set macro_names = [print_lower, print_upper] -%}
    
    {% for macro_name in macro_names %} 
        {{ macro_name("test") }} 
    {% endfor %}
    

    and

    {% macro print_lower(string) %}
        {{ print(string|lower) }}
    {% endmacro %}
    
    {% macro print_upper(string) %}
        {{ print(string|upper) }}
    {% endmacro %}
    

    enter image description here