iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 20
0

話說進行到了第二十篇還停在 Router,我幾乎要確定三十篇寫不完想講的東西了。一定是之前碎念太多了。今天要來繼續談 Router 的其它功能。

scope

在 Router 中,我們可以用 scope 來分組不同的 URI 路徑。來打開 router.ex 檔案,將最底下的 scope "/api" 區塊的註釋移除,加上 .APIas: :api。在區塊裡放進一個 get 及一個 resources,變成這樣:

  scope "/api", HelloPhxWeb.API, as: :api do
    pipe_through :api
    get "/", DocController, :index
    resources "/users", UsersController
  end

回到 shell,用 mix phx.routes 指令就會看到生出這樣的 routes:

api_doc_path GET /api HelloPhxWeb.API.DocController :index
api_user_path GET /api/users HelloPhxWeb.API.UserController :index
api_user_path GET /api/users/:id/edit HelloPhxWeb.API.UserController :edit
api_user_path GET /api/users/new HelloPhxWeb.API.UserController :new
api_user_path GET /api/users/:id HelloPhxWeb.API.UserController :show
api_user_path POST /api/users HelloPhxWeb.API.UserController :create
api_user_path PATCH /api/users/:id HelloPhxWeb.API.UserController :update
              PUT /api/users/:id HelloPhxWeb.API.UserController :update
api_user_path DELETE /api/users/:id HelloPhxWeb.API.UserController :delete

重點在於放在 scope do...end 區塊內的 URI,都是對於 scope 第一個參數的相對路徑

由於 scope 裡可以用 pipe_throigh 來決定這群 URI 要流過的 pipeline,所以實務上最常用來劃分不同功能的群組,舉例來說,如果有公開的頁面、需要登入的頁面跟管理者的後台,可能會這樣劃分:

scope "/" do
  pipe_through :browser
  #...
end

scope "/dashboard" do
  pipe_through [:browser, :auth]
end

scope "/admin" do
  pipe_through [:browser, :auth, :check_admin]
end

讓 View、Controller 生在符合 scope 的資料夾

由於 mix phx.gen.html 會把 view 及 controller 直接放在 lib/專案名稱_web/viewlib/專案名稱_web/controller根目錄下,所以如果要依 scope 的名稱來組織檔案夾的話,可以使用 --web 參數:

$ mix phx.gen.html Admin Dashboard dashboards --web Admin

用模版產生 API CRUD

除了網頁表單的 CRUD 之外,Phoenix 也提供了生成 API CRUD 指令:

$ mix phx.gen.json API User users name:string age:integer --web API
* creating lib/hello_phx_web/controllers/api/user_controller.ex
* creating lib/hello_phx_web/views/api/user_view.ex
* creating test/hello_phx_web/controllers/api/user_controller_test.exs
* creating lib/hello_phx_web/views/changeset_view.ex
* creating lib/hello_phx_web/controllers/fallback_controller.ex
* creating lib/hello_phx/api/user.ex
* creating priv/repo/migrations/20180115185210_create_users.exs
* creating lib/hello_phx/api/api.ex
* injecting lib/hello_phx/api/api.ex
* creating test/hello_phx/api/api_test.exs
* injecting test/hello_phx/api/api_test.exs

Add the resource to your API :api scope in lib/hello_phx_web/router.ex:

    scope "/api", HelloPhxWeb.API do
      pipe_through :api
      ...
      resources "/users", UserController
    end


Remember to update your repository by running migrations:

    $ mix ecto.migrate

跑完 mix ecto.migrate 後,用瀏覽器打開 http://localhost:4000/api/users,就能看到 JSON 的回傳值了:

https://ithelp.ithome.com.tw/upload/images/20180118/20103390r0WwZf2glG.png

巢狀 routes

如果要產生巢狀的 routes,只要這樣做就可以了:

resources "/users", UserController do
  resources "/posts", PostController
end

這樣就會產生以下的路由:

user_post_path GET /users/:user_id/posts HelloWeb.PostController :index
user_post_path GET /users/:user_id/posts/:id/edit HelloWeb.PostController :edit
user_post_path GET /users/:user_id/posts/new HelloWeb.PostController :new
user_post_path GET /users/:user_id/posts/:id HelloWeb.PostController :show
user_post_path POST /users/:user_id/posts HelloWeb.PostController :create
user_post_path PATCH /users/:user_id/posts/:id HelloWeb.PostController :update
               PUT /users/:user_id/posts/:id HelloWeb.PostController :update
user_post_path DELETE /users/:user_id/posts/:id HelloWeb.PostController :delete

要注意的是這個例子中上層的路由的參數名稱,會變成 :user_id,此名稱是由其 resource 名稱決定的。

Path Helper

當我們用 mix phx.routes 來看產生出的路由時,每行的第一個名稱是在程式裡用來產生路徑字串的 helper 函式。我們來試試看:

iex> import HelloPhx.Router.Helpers
iex> alias HelloPhx.Endpoint
iex> api_user_path(Endpoint, :index)
"/api/users"

iex> api_user_path(Endpoint, :show, 17)
"/api/users/17"

iex> api_user_path(Endpoint, :new)
"/api/users/new"

這個路徑 helper 通常用在 View 、Template 或是 Controller 中來產生要前往的頁面路徑。如果你想要改變這個 helper 函式的名稱時,可以使用 :as 選項:

scope "/api", HelloPhxWeb.API, as: :v1 do
  resources "/users", UsersController
end

會產生出

v1_user_path GET /api/users HelloPhxWeb.API.UserController :index
v1_user_path GET /api/users/:id/edit HelloPhxWeb.API.UserController :edit
...

重點回顧

  • scope 用來分組路由
  • 每個 scope 可以用 pipe_through/1 來選擇要流經的 pipeline
  • 巢狀 routes 就是放在 resources 的 do...end 區塊裡
  • Path Helper 函式用在程式裡產生要前往的頁面路徑
  • as: 選項可以改變 helper 函式的名稱

Happy hacking! 明天見。


上一篇
Router.part_1
下一篇
沒有很 thin 的 Controller
系列文
函數式編程: 從 Elixir & Phoenix 入門。31

1 則留言

0
taiansu
iT邦新手 5 級 ‧ 2018-01-17 06:02:56

已更新

我要留言

立即登入留言