在 Phoenix 中动态定义顶级路由 routes.ex
Dynamically defining top level routes in Phoenix routes.ex
我想做的是根据可用于数据库中特定模型的 slug 动态路由顶级路径,例如 GitHub 对 user/org 名称的处理方式,例如 https://github.com/elixir-lang
和 https://github.com/phoenixframework
,但我似乎无法在 PhoenixFramework 中理解它。
到目前为止我在 routes.ex
中尝试的是:
Enum.each(MyApp.Repo.all(MyApp.User), fn section ->
get "/#{user.username}", UserController, :show, assigns: %{"username" => user.username}
end)
但我在尝试编译应用程序时遇到以下错误:
== Compilation error on file web/router.ex ==
** (ArgumentError) repo MyApp.Repo is not started, please ensure it is part of your supervision tree
lib/ecto/query/planner.ex:91: Ecto.Query.Planner.cache_lookup/3
lib/ecto/query/planner.ex:72: Ecto.Query.Planner.query/4
lib/ecto/repo/queryable.ex:91: Ecto.Repo.Queryable.execute/5
lib/ecto/repo/queryable.ex:15: Ecto.Repo.Queryable.all/4
web/router.ex:25: (module)
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8
routes.ex
是 DSL,它是在编译时解析的,而不是在运行时解析的。错误消息中的前两个词是 Compilation error
。这意味着,您不能在路由中使用数据库。
相反,尝试像这样定义顶级路由:
get /:user_slug, UserController, :show
在您的控制器中,检查此用户是否存在于数据库中,如果不存在,则return 404。
我写了一篇博客 post 关于如何做到这一点:
http://www.adamcz.com/blog/pretty-urls-with-phoenix
如果数据库中已有 slug,只需在路由器文件中指定参数即可:
resources "/users", UserController, only: [:index, ...], param: "slug"
然后在您的控制器中查找该参数:
def show(conn, %{"slug" => slug}) do
user = Repo.get_by(User, slug: slug)
# ...
end
我想做的是根据可用于数据库中特定模型的 slug 动态路由顶级路径,例如 GitHub 对 user/org 名称的处理方式,例如 https://github.com/elixir-lang
和 https://github.com/phoenixframework
,但我似乎无法在 PhoenixFramework 中理解它。
到目前为止我在 routes.ex
中尝试的是:
Enum.each(MyApp.Repo.all(MyApp.User), fn section ->
get "/#{user.username}", UserController, :show, assigns: %{"username" => user.username}
end)
但我在尝试编译应用程序时遇到以下错误:
== Compilation error on file web/router.ex ==
** (ArgumentError) repo MyApp.Repo is not started, please ensure it is part of your supervision tree
lib/ecto/query/planner.ex:91: Ecto.Query.Planner.cache_lookup/3
lib/ecto/query/planner.ex:72: Ecto.Query.Planner.query/4
lib/ecto/repo/queryable.ex:91: Ecto.Repo.Queryable.execute/5
lib/ecto/repo/queryable.ex:15: Ecto.Repo.Queryable.all/4
web/router.ex:25: (module)
(stdlib) erl_eval.erl:669: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8
routes.ex
是 DSL,它是在编译时解析的,而不是在运行时解析的。错误消息中的前两个词是 Compilation error
。这意味着,您不能在路由中使用数据库。
相反,尝试像这样定义顶级路由:
get /:user_slug, UserController, :show
在您的控制器中,检查此用户是否存在于数据库中,如果不存在,则return 404。
我写了一篇博客 post 关于如何做到这一点:
http://www.adamcz.com/blog/pretty-urls-with-phoenix
如果数据库中已有 slug,只需在路由器文件中指定参数即可:
resources "/users", UserController, only: [:index, ...], param: "slug"
然后在您的控制器中查找该参数:
def show(conn, %{"slug" => slug}) do
user = Repo.get_by(User, slug: slug)
# ...
end