Можете ли вы добавить пользовательские функции помощника по маршруту в Phoenix Router.Helpers? - PullRequest
0 голосов
/ 22 января 2019

Я хочу реализовать пользовательскую вспомогательную функцию маршрута для модели 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 голосов
/ 04 апреля 2019

У меня был похожий вариант использования, и если вы хотите также автоматически получить своего собственного помощника, где есть другие помощники маршрута, я смог добиться этого, определив свой собственный модуль new и импортировав его. это где приложение phoenix уже импортирует помощники маршрутизатора: функции controller и view в модуле MyAppWeb и (если вы хотите использовать его также в своих тестах) функцию using в 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

Тогда вы добавите import MyAppWeb.RouteHelpers к вышеупомянутым функциям.

Я новичок в Elixir / Phoenix, поэтому я не уверен, что это «правильный путь», но он кажется логичным и избавляет вас от необходимости импортировать определенные методы из модуля PostView везде, где вы можете вызвать маршрут.

0 голосов
/ 22 января 2019

Нет абсолютно никакой разницы, куда вы помещаете функцию.Функции в Elixir полностью не сохраняют состояния (и не существует иерархий классов), то есть они могут быть вставлены буквально в любой модуль (если вызывающая точка может получить доступ к этому модулю, что будет нормой, если вы неИспользуешь зонтики).

Во-вторых, когда вы обнаружите, что нуждаетесь в функции как в контроллере, так и в представлении (и даже в шаблоне), это явный признак , вы делаете это неправильно .Диким предположением было бы то, что вы хотите использовать contextxts .


Я мог бы объяснить, почему он «работает не так, как ожидалось», и что вызывает эту ошибку, если у вас была ошибкасообщение или как сообщение.Я ожидаю, что проблема связана с 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.

...