Phoenix Framework中的可选路由参数

时间:2016-07-01 11:59:07

标签: elixir phoenix-framework

我已经开始自学Phoenix Framework并且他们的文档非常好。然而,在指定可选路由参数时,我遇到了绊脚石。 Phoenix Framework Routing Documentation没有提到这个特征,所以我假设责任落在了开发者身上以提出解决方案。

我将列出我的用例:

  1. 用户访问/page/test网站,自定义Plug然后实施一些代码以查找或为该连接分配locale
  2. 由于路径中没有:locale参数,因此我的管道中的行使用默认值plug HelloPhoenix.Plugs.Locale, "en"
  3. 用户访问/fr/page/test处的网站,并在管道中执行相同的代码,除了路由中存在:locale参数的时间,自定义插件(HelloPhoenix.Plugs.Locale)。
  4. 现在从路由的角度来看,如果我不能指定: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
    

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

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

2 个答案:

答案 0 :(得分:7)

您可以使用简单的插件:

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

然后将此插头放在endpoint.ex

中的路由器之前
  plug MyApp.SetLocale
  plug MyApp.Router
end

通过这种方式,您可以确信在您到达路由器之前已经设置了区域设置。您根本不需要在路由器中提及它。

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

答案 1 :(得分:2)

正如我在问题中所提到的,我提出了一个适用于我的解决方案,但我不确定它是正确的还是最简单的解决方案(特别是如果路由变得更复杂)......

我的解决方案使用Enum.each循环遍历前缀列表,然后只需要指定一次路由。这似乎有效:

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

  # Loop over list containing prefix :locale and no prefix.
  Enum.each ["/:locale", "/"], fn prefix ->
    # No need to duplicate routes
    get prefix <> "/page/:slug", PageController, :show
  end
end