evanmiller/erlydtl — pull request #64 by pguyot (2013-01-31 16:29:13+00:00)
Title: Add support for variables (and expressions) in include and ssi tags

Django documentation mentions that first argument of include and ssi tags (the template name/path of included file) can be a literal or a context variable. In fact, an expression with filters seem to also work. Make it likewise in erlydtl.

The implementation is a compromise based on possible differences between runtime and compile time. Previous behavior is maintained identically. Yet, there are subtle differences between a partial template included from an expression (searched at runtime) and a partial template included from a literal (searched at compile time):
- if compile time variables contain structures that cannot be abstracted or that would not work at runtime, then compilation or rendering will fail. Typically, functions cannot be abstracted (a workaround would be to serialize them to binary, but they still might fail at runtime);
- to avoid failure with `blocktrans_fun`, this option is simply removed and not passed from compile time to runtime. As a consequence, partials included at runtime cannot contain translated blocks;
- the name of the module is guessed based on a heuristic that works with [ChicagoBoss](https://github.com/evanmiller/ChicagoBoss) but might fail with other applications using erlydtl. Indeed there is no way to guess what a production environment wants to compile a template to. As a result, partials included at runtime might require to be compiled at runtime a second time (under a different module name). This recompilation might fail as the environment might differ;
- no effort is made to recompile the included template if it is already available. This is a serious drawback for development but is required as there is no way to make sure user wants the template to be recompiled at runtime based on information available at compile_time. Looking for the source of the template might fail in some deployments and can be judged expensive anyway.

Some of these drawbacks could be alleviated by changing a little bit the coupling between erlydtl and the frameworks. For example, if `blocktrans_fun` was replaced by a `{M, F}` pair, it could be abstracted. Likewise, instead of passing the module name, the client could provide a `{M, F}` reference to a function that transforms a filename into a module, and this function could be called at runtime from `erlydtl_runtime:include_file/6`.