例如我有:
-record(usr,{name,email}).
...
Usr1 = #usr{name="John", email="john@host.com"},
Usr2 = #usr{name="Jane", email="jane@host.com"},
Usr3 = #usr{name="Alex", email="alex@host.com"},
{ok, Result} = template_dtl:render([{users, [Usr1, Usr2, Usr3]}]),
...
Run Code Online (Sandbox Code Playgroud)
我想这样使用它:
{% block content %}
{% for user in users %}
<a href="mailto:{{user.email}}">Send mail to {{user.name}}</a>
{% endfor %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)
有人遇到过同样的问题吗?
记录是元组之上的语法糖。Usr1,Usr2并且Usr3just 是元组,并且准确地说:
Usr1 = {usr, "John", "john@host.com"},
Usr2 = {usr, "Jane", "jane@host.com"},
Usr3 = {usr, "Alex", "alex@host.com"}.
Run Code Online (Sandbox Code Playgroud)
模板不知道如何解释这些记录,因为它在编译时不知道记录定义。
您的问题有三种解决方案。在所有情况下,模板都是相同的,您应该按照您的方式user.email编写。user.name
record_info编译选项正是为了告诉 erlydtl 模板变量中使用的记录。
erlydtl:compile_template(Template, TemplateModuleName, [{record_info, [{usr, record_info(fields, usr)}]).
Run Code Online (Sandbox Code Playgroud)
缺点是您可能不会给erlydtl:compile*自己打电话,因此添加record_info选项可能会很困难。此外,调用此函数的代码段必须知道您可能需要移动到文件的记录定义.hrl。
这是Soup d'Campbells在他们的评论中建议的。您还可以使用编译时函数record_info/2来实现此目的。最简单的确实是proplist()形式:
lists:zip(record_info(fields, usr), tl(tuple_to_list(Usr1))).
Run Code Online (Sandbox Code Playgroud)
tuple_to_list(Usr1)计算结果为[usr, "John", "john@host.com"],而record_info(fields, usr)等于[name, email]。
记录并不适合使用公共访问器 ( user.name) 捕获数据结构,因为它们最好在给定模块的本地进行维护,因为这使得代码更新更加容易。或者,您可以定义一个将导出和访问器的模块(称为usr或app_user但不是user因为这样的模块已经存在)。name/1email/1
这里的 Erlydtl 魔法是基于以前称为参数化模块的功能,更准确地说是使用元组而不是原子作为模块名称来调用函数的能力。您实际上并不需要参数化模块,只需传递与现有模块匹配的元组即可。
例如,您的app_user模块可能如下所示:
-module(app_user).
-export([new/2, name/1, email/1]).
-record(?MODULE, {name :: string(), email :: string()}). % private to this module.
-type app_user() :: #?MODULE{}.
-spec new(string(), string()) -> app_user().
new(Name, Email) -> #?MODULE{name = Name, email = Email}.
-spec name(app_user()) -> string().
name(#?MODULE{name = Name}) -> Name.
-spec email(app_user()) -> string().
email(#?MODULE{email = Email}) -> Email.
Run Code Online (Sandbox Code Playgroud)
(?MODULE使用而不是app_user因为这仅在记录名称与模块名称匹配时才有效,并且即使您重命名模块,此代码也将有效)。
然后,在您的代码中,而不是:
Usr1 = #usr{name = "John", email = "john@host.com"}
Run Code Online (Sandbox Code Playgroud)
你会写:
Usr1 = app_user:new("John", "john@host.com").
Run Code Online (Sandbox Code Playgroud)
Usr1 只是一条记录,或更准确地说是元组:
{app_user, "John", "john@host.com"}.
Run Code Online (Sandbox Code Playgroud)
尽管如此,Erlydtl 仍然能够Usr1直接进行处理。它将认为它是一个参数化模块,作为app_user一个模块存在(它是上面的模块)。因此,在模板渲染期间,它将调用app_user:name/1和app_user:email/1访问器函数,并向它们传递整个记录。
| 归档时间: |
|
| 查看次数: |
764 次 |
| 最近记录: |