Dylan-aidkr
Split router while using verified routes
trying to split the large router file
this is some simple representation of my router
# part of MyAppWeb.Router.ex
scope "/shop/:shop_id" do
scope "/users" do
live "/"
live "/:user_id"
# large sub routes
...
end
scope "/items" do
live "/"
live "/:item_id"
# large sub routes
...
end
end
I searched, and it seems there are 3 options for splitting router.
1. using “forward”
not possible, as it does not allow to forward to route with dynamic segment
== Compilation error in file lib/my_app_web/router.ex ==
** (ArgumentError) dynamic segment "/shop/:shop_id/users" not allowed when forwarding. Use a static path instead
2. using “match”
not able to catch error with verified routes
scope "/shop/:shop_id" do
match :*, "/users/*path", MyAppWeb.UserRouter, :any
match :*, "/items/*path", MyAppWeb.ItemRouter, :any
end
with this method invalid path like a “/shop/1234/users/1234/no-exist-path” was not caught by the verified routes.
3. plug routers to Endpoint.ex
not sure if it would work. how to declare verified routes on this setting?
# part of Endpoint.ex
defmodule MyAppWeb.Endpoint do
...
plug MyAppWeb.Router
plug MyAppWeb.UserRouter
plug MyAppWeb.ItemRouter
end
code above is not working. it seems the Router return NoRouteError before UserRouter.
there is a solution for this(Using multiple routers in Phoenix - #3 by alexgleason)
but still not sure how deal with the VerifiedRoutes.
i need to fix code below to properly handle multiple router.
# part of MyAppWeb.ex
use Phoenix.VerifiedRoutes,
endpoint: MyAppWeb.Endpoint,
router: [MyAppWeb.Router, MyAppWeb.UserRouter], # array of router is not valid input
statics: MyAppWeb.static_paths()
please help!
Marked As Solved
stephane
Hey @Dylan-aidkr,
One simple solution is to create a macro to split your router.
example
require MySubRoutes
....
# part of MyAppWeb.Router.ex
scope "/shop/:shop_id" do
scope "/users" do
live "/"
live "/:user_id"
# large sub routes
...
end
MySubRoutes.items()
end
defmodule MySubRoutes do
defmacro items do
quote do
scope "/items" do
live "/"
live "/:item_id"
...
end
end
end
end
This allow you to keep your router clean and forward easily path params.
Also Liked
chrismccord
You can either use Phoenix.VerifiedRoutes, router: ... in the context where you want to use different routers, or use Phoenix.VerifiedRoutes.path/3 and explicitly pass the router:
@doc ~S'''
Generates the router path with route verification.
See `sigil_p/1` for more information.
Warns when the provided path does not match against the router specified
in `use Phoenix.VerifiedRoutes` or the `@router` module attribute.
## Examples
import Phoenix.VerifiedRoutes
redirect(to: path(conn, MyAppWeb.Router, ~p"/users/top"))
redirect(to: path(socket, MyAppWeb.Router, ~p"/users/#{@user}"))
~H"""
<.link to={path(@uri, MyAppWeb.Router, ~p"/users?page=#{@page}")}>profile</.link>
<.link to={path(@uri, MyAppWeb.Router, ~p"/users?#{@params}")}>profile</.link>
"""
'''
mentero
We went with
match :*, "/users/*path", MyAppWeb.UserRouter
for router splitting (using macros was causing frequent big recompiles for us)
We are used to alias the Router we want to refer before using path helpers
alias MyAppWeb.UserRouter.Helpers, as: Routes
#...
Routes.users_path(...)
We did not move to verified routes yet, but I would assume we would need to move from aliasing to use Phoenix.VerifiedRoutes
stephane
You’re right about macro makes it harder to debug / detect errors.
But in this case, your custom macro is just to use Phoenix.(Live).Router macros. Actually the phoenix router contains essentially macros (live, scope, resources…). There are no custom application logic inside yours.
This solution makes it easy to split into smaller files, handle params and upper scopes and verified routes still works ![]()
But very interested if any other ways to solve all of these issues at once.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #podcasts
- #code-sync
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








