是否可以向Phoenix Router.Helpers添加自定义路由帮助器功能?

时间:2019-01-22 03:50:17

标签: elixir phoenix-framework

我想为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

2 个答案:

答案 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模块中的viewMyAppWeb函数,以及(如果您还想在测试中使用它){ 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模块中导入特定方法。路线。