Elixir Phoenix:我可以从模板调用上下文函数吗?
Elixir Phoenix: Can I call a context function from a template, and should I
我想以文章形式(用于创建和更新)显示 article_categories
的列表作为下拉输入。
我的博客上下文 (blog.ex
) 中有一个函数可以通过 Ecto 检索所有类别并将结果格式化为可下拉列表:
defmodule MyApp.Blog do
import Ecto.Query, warn: false
alias MyApp.Repo
alias MyApp.Blog.ArticleCategory
def get_categories() do
MyApp.Repo.all from c in ArticleCategory, select: {c.title, c.id}
end
end
在我的模板 (templates/article/form.html.heex
) 中,我这样称呼我的类别:
<%= select f, :category_id, MyApp.Blog.get_categories(), prompt: [key: "Choose your category"] %>
视觉上我得到了我想要的结果,但是...文献似乎暗示将我的类别作为分配传递。
这样做有问题吗? (性能?设计?)
我完全赞成将该逻辑放入控制器中。这里的主要动机是关注点分离:
- 你的控制器负责解析传入的参数并从data/business层
获取正确的数据
- 您的视图层负责将数据呈现给用户
其中一个优点是您最终会得到一个更易于维护和测试的系统。
我想很难看出为什么这是最佳实践,但随着应用程序的增长,它会显示出来。
例如:一项新要求是 get_categories
现在仅列出用户有权访问的类别。使用控制器分配,您可以创建一个控制器测试,其中包含类似 assert conn.assigns.categories == ["one", "two"]
的内容。但是,当您在视图中获取类别时,测试将变成类似于 assert html_response(conn, 200) =~ "<li>one</li><li>two</li>"
的东西,它更脆弱(即它不能保证没有项目 'three',或者如果您添加 class 到每个 li
元素,那么你还必须更新测试。
我想以文章形式(用于创建和更新)显示 article_categories
的列表作为下拉输入。
我的博客上下文 (blog.ex
) 中有一个函数可以通过 Ecto 检索所有类别并将结果格式化为可下拉列表:
defmodule MyApp.Blog do
import Ecto.Query, warn: false
alias MyApp.Repo
alias MyApp.Blog.ArticleCategory
def get_categories() do
MyApp.Repo.all from c in ArticleCategory, select: {c.title, c.id}
end
end
在我的模板 (templates/article/form.html.heex
) 中,我这样称呼我的类别:
<%= select f, :category_id, MyApp.Blog.get_categories(), prompt: [key: "Choose your category"] %>
视觉上我得到了我想要的结果,但是...文献似乎暗示将我的类别作为分配传递。
这样做有问题吗? (性能?设计?)
我完全赞成将该逻辑放入控制器中。这里的主要动机是关注点分离:
- 你的控制器负责解析传入的参数并从data/business层 获取正确的数据
- 您的视图层负责将数据呈现给用户
其中一个优点是您最终会得到一个更易于维护和测试的系统。
我想很难看出为什么这是最佳实践,但随着应用程序的增长,它会显示出来。
例如:一项新要求是 get_categories
现在仅列出用户有权访问的类别。使用控制器分配,您可以创建一个控制器测试,其中包含类似 assert conn.assigns.categories == ["one", "two"]
的内容。但是,当您在视图中获取类别时,测试将变成类似于 assert html_response(conn, 200) =~ "<li>one</li><li>two</li>"
的东西,它更脆弱(即它不能保证没有项目 'three',或者如果您添加 class 到每个 li
元素,那么你还必须更新测试。