Phoenix Framework中的可选路由参数

too*_*cts 5 elixir phoenix-framework

我已经开始自学Phoenix Framework了,他们的文档非常好.然而,在指定可选路由参数时,我遇到了绊脚石.在凤凰框架路由文档并没有提及这是一个功能,所以我假设的责任就落在了开发拿出一个解决方案.

我将列出我的用例:

  1. 用户访问站点/page/test,然后自定义插件实现一些代码来查找或分配locale连接.
  2. 由于没有:locale路径参数,使用默认的按在我行的管道,这是plug HelloPhoenix.Plugs.Locale, "en".
  3. 用户访问site at /fr/page/test,并且相同的代码在管道中执行,除了:locale路径中存在参数的时间,自定义Plug(HelloPhoenix.Plugs.Locale).

现在从路由的角度来看,如果我不能指定:locale参数是可选的,我最终会得到双倍的路由数,例如:

scope "/", HelloPhoenix do
  use_pipeline :browser
  plug HelloPhoenix.Plugs.Locale, "en"

  # Route without locale
  get "/page/:slug", PageController, :show
  # Route with locale
  get "/:locale/page/:slug", PageController, :show
end
Run Code Online (Sandbox Code Playgroud)

正如您所知,如果没有指定可选路由参数的能力,这可能会很快变得非常艰巨和重复.

不,我确实有一个解决方法,我将在答案中发布,但我不确定它是否正确,以及(b)最简单的解决方案,因为我是Erlang,Elixir和Phoenix的新手(我来自Ruby和PHP OOP的背景.

Gaz*_*ler 8

你可以有一个简单的插头,如:

defmodule MyApp.SetLocale do

  @locales ~w{en fr}

  def init(opts), do: opts

  def call(conn, _opts) do
    case conn.path_info do
      [locale | rest] when locale in @locales ->
        %{conn | path_info: rest}
        |> Plug.Conn.assign(:locale, locale)
      _  -> Plug.Conn.assign(conn, :locale, "en")
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后将此插头放在endpoint.ex中的路由器之前

  plug MyApp.SetLocale
  plug MyApp.Router
end
Run Code Online (Sandbox Code Playgroud)

这样您就可以确信在到达路由器之前已经设置了区域设置.您根本不需要在路由器中提及它.

如果您输入的区域设置不在该区域中,则此技术将为404 @locales.