我想为Post模型实现一个自定义的路由帮助器函数,该函数可以链接到线程根,或者在Post是对线程的答复的情况下链接到带有散列的线程根(它们共享Post型号)。
在哪里可以定义此函数,以使其可以从控制器,视图和模板中轻松访问?
我已经能够像在PostView中那样实现该功能了,但是现在我想从控制器中使用它,并且看起来像住在Router.Helpers中就像其他URL一样合适。帮手。
我已经尝试在路由器中实现它,但这也无法按预期工作。
def post_path(conn, action, post) do
if Post.thread?(post) do
"#{board_thread_path(conn, action, post.board.path, post)}"
else
"#{board_thread_path(conn, action, post.board.path, post.thread)}#post-#{post.number}"
end
end
答案 0 :(得分:0)
放置函数的位置绝对没有区别。 Elixir中的函数是完全无状态的(并且没有类层次结构),这意味着它们可以放在字面上的 any 模块中(只要调用点可以访问该模块即可,除非有此规范,否则您正在使用雨伞)。
第二,当您发现自己需要同时在控制器和视图(甚至模板)中使用某个功能时,这显然是您做错了的信号。您可能想使用contexts。
我可能已经解释了为什么它“也无法按预期运行”,以及如果您收到错误消息或类似的帖子会导致此错误。我希望问题出在您的模型(?)中,其中一个board_thread_path/4
注入了use Blah
。我不知道它是公开注入还是私下注入。如果是公开的,只需使用完全限定的名称即可调用它:
def post_path(conn, action, post) do
path = MyApp.MyModule.board_thread_path(conn, action, post.board.path, post)
if Post.thread?(post),
do: path, else: path <> "#post-#{post.number}"
end
如果是私密的,则将其包装到公共位置(请记住:这可能是错误的方法),然后从各处使用完全限定的名称调用新包装器函数。
为避免使用FQ名称,可以使用Kernel.SpecialForms.import/2
。
答案 1 :(得分:0)
我有一个类似的用例,如果您还想在其他路由助手可用的地方自动获得您的自定义助手,则可以通过定义我自己的 new 模块并实现将其导入到已经安装了phoenix应用程序的路由器助手中:controller
模块中的view
和MyAppWeb
函数,以及(如果您还想在测试中使用它){ using
中的1}}函数。
因此您的新文件可能是MyAppWeb.ConnCase
:
lib/my_app_web/route_helpers.ex
然后您将defmodule MyApp.RouteHelpers do
import MyAppWeb.Router.Helpers, only: [board_thread_path: 4]
alias MyApp.Post
def post_path(conn, action, post) do
if Post.thread?(post) do
"#{board_thread_path(conn, action, post.board.path, post)}"
else
"#{board_thread_path(conn, action, post.board.path, post.thread)}#post-#{post.number}"
end
end
end
添加到上述功能中。
我是Elixir / Phoenix的新手,所以我不确定这是否是“正确的方法”,但这似乎合乎逻辑,这使您不必从可能会调用的PostView模块中导入特定方法。路线。