スポンサーリンク

2015年6月1日

Phoenixのルーティング(Router)について分かったこと

タイトル: Phoenixのルーティング(Router)について分かったこと

目的: Phoenixアプリケーションのルーティング(Router)について分かったことを記述する。

実施環境:
OS: Windows8.1
Erlang: Eshell V6.4
Elixir: v1.0.4
Phoenix Framework: v0.13.1
Node.js: v0.12.4

目次:

  1. 概要
  2. mix phoenix.routesコマンド
  3. Router.exへの記述例
  4. PathHelpersの使い方
  5. おまけ

1.概要

1.1
注意!!
この記事は、Phoenix - Guides Routingを素人翻訳して分かったことを書いています。
原文を丸々翻訳しているわけではないので、
流れや説明がおかしいところ多々ありますが、その点注意して下さい。
英語が分かる方は、公式を見た方が確実です。

また、管理人の英語力は本人がドン引きするほど低いので、
間違った解釈及び理解している部分が多分にあると思います。

それでも構わないという方は見て頂けたら嬉しいです。

また、ご指摘等があれば受け付けておりますゆえ、遠慮なくお願いします。
特に間違えて習得している部分は教えて頂ければ、本当に助かります。

1.2
ルーティング(Router)って何?
ネットワークにおけるルーティングではない。(全く関係ないわけではないが・・・)

RouterはPhoenixアプリケーションの主要なハブ。
HTTPの要求をアクション、チャネル、コントローラなどに一致させる。

1.3
あらかじめ、テスト用のプロジェクトは作成しておいて下さい。

管理人は、以下の内容で実施しております。
  • アプリケーション名: hello_phoenix
  • 設定は全てデフォルト
  • 作業は、hello_phoenixディレクトリ内で実施(コマンドプロンプトを含む)

2.mix phoenix.routesコマンド

2.1
コマンドプロンプトからhello_phoenixディレクトリ内で以下のコマンドを実行する。
コマンド: mix phoenix.routes

出力結果は・・・
page_path  GET  /                  HelloPhoenix.PageController.index/2

と出力される。
つまり・・・なんだってばよこれ?

2.2
ルーティング先を設定しているファイルとなると・・・
hello_phoenix/web/router.exを開いて見てみよう。

scope部分にルーティング先を設定している部分がある。
scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
end

この部分である。
get "/", PageController, :index

2.3
2.1と2.2の内容からmix phoenix.routesコマンドは、
hello_phoenixアプリケーションのルーティング一覧を出力してくれていることが見て取れる。

本当かな?なら、ルーティング先を追加してみよう!

2.4
先ほどのscope部分に以下の記述を追加する。
追加: get "/users", UserController, :index

scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  get "/users", UserController, :index
end

※実際にコントローラを作成していなくても問題なく動作する。

2.5
再び、先ほどのコマンドを実行しよう。
コマンド: mix phoenix.routes

出力を見てみると・・・
page_path  GET  /                  HelloPhoenix.PageController.index/2
user_path  GET  /users             HelloPhoenix.UserController.index/2

追加された。
ルーティング先をrouter.exに追加し、mix phoenix.routesコマンドすると、
router.exに記述したルーティング先の一覧が見れる。

何に使えるかって?
例えば、一行で複数のルーティング先になる記述があるとしたら?
そういった記述もルーティング先一覧に全て出力してくれます。

確認に便利ですね!

3.Router.exへの記述例

さて、幾つかの記述の仕方を紹介しようと思います。

3.1
2.5でも書いてある、一行で複数として認識される記述でも書きましょう。
router.exのscopeに追加で記述していきます。

先ほどのUserControllerのルーティングを以下のように修正して下さい。
修正: resources "/users", UserController

scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  get "/users", UserController, :index
end

コマンドを実行しましょう。
コマンド: mix phoenix.routes

出力結果は・・・
page_path  GET  /                  HelloPhoenix.PageController.index/2
user_path  GET     /users             HelloPhoenix.UserController.index/2
user_path  GET     /users/:id/edit    HelloPhoenix.UserController.edit/2
user_path  GET     /users/new         HelloPhoenix.UserController.new/2
user_path  GET     /users/:id         HelloPhoenix.UserController.show/2
user_path  POST    /users             HelloPhoenix.UserController.create/2
user_path  PATCH   /users/:id         HelloPhoenix.UserController.update/2
             PUT     /users/:id         HelloPhoenix.UserController.update/2
user_path  DELETE  /users/:id         HelloPhoenix.UserController.delete/2

いきなり増えましたねw

あの一行だけでこれだけのルーティング先がマッチしてくれるんです。
すごいですよね・・・

ちなみに、/users/:idってどんなパスが来た時動作するのかってところなのですが・・・

例えば、
"http://localhost:4000/users/darui"
"http://localhost:4000/users/999"(Railsだと数値で管理するらしいので)
ってな具合のURL(パス)が来た時ですね。

Railsライクと言うことは数値が入っている方で意識しておいた方が良い気がしますね!

:idは、Phoenixアプリケーションにページを追加してみる。(その2)の:messengerの例を見て下さい。
ようは、ただのラベルですね。

でも、特定のルーティングだけ欲しい時やその逆の時はどうすればいいんでしょうか?

3.2
以下の記述を追加して下さい。
追加: resources "posts", PostController, only: [:index, :show]

コマンドを実行しましょう。
コマンド: mix phoenix.routes

二行増えましたね。
post_path  GET     /posts             HelloPhoenix.PostController.index/2
post_path  GET     /posts/:id         HelloPhoenix.PostController.show/2

only: [アクション名...]で特定のルーティングだけ選択できます。

3.3
以下の記述を追加して下さい。
追加: resources "comments", CommentController, except: [:delete]

コマンドを実行しましょう。
コマンド: mix phoenix.routes

七行増えましたね。
comment_path  GET     /comments           HelloPhoenix.CommentController.index/2
comment_path  GET     /comments/:id/edit  HelloPhoenix.CommentController.edit/2
comment_path  GET     /comments/new       HelloPhoenix.CommentController.new/2
comment_path  GET     /comments/:id       HelloPhoenix.CommentController.show/2
comment_path  POST    /comments           HelloPhoenix.CommentController.create/2
comment_path  PATCH   /comments/:id       HelloPhoenix.CommentController.update/2
                      PUT     /comments/:id       HelloPhoenix.CommentController.update/2

以下の記述をした時と何が違うのでしょう?
get "/users", UserController, :index

そうですね。deleteの行が消えています!!
つまり、特定のルーティングだけ除外できるということです。

4.PathHelpersの使い方

Path Helpersは、Router.Helpersモジュールに定義されている関数。
どんな、URLやパスが出るか試すことができます。

4.1
以下のコマンドを実行して対話モードを起動しましょう。
hello_phoenix>iex -S mix

4.2
以下を実行してみて下さい。
iex> HelloPhoenix.Router.Helpers.page_path(HelloPhoenix.Endpoint, :index)

出力結果・・・
"/"

ルートが返ってくるだけですね。

4.3
また、以下の内容を実行してみて下さい。

iex(1)> import HelloPhoenix.Router.Helpers
nil
iex(2)> alias HelloPhoenix.Endpoint
nil
iex(3)> user_path(Endpoint, :index)
"/users"
iex(4)> user_path(Endpoint, :show, 17)
"/users/17"
iex(5)> user_path(Endpoint, :create)
"/users"
iex(6)> user_path(Endpoint, :edit, 37)
"/users/37/edit"
iex(7)> user_path(Endpoint, :update, 37)
"/users/37"
iex(8)> user_path(Endpoint, :delete, 17)
"/users/17"
iex(9)> user_path(Endpoint, :show, 17, admin: true, active: false)
"/users/17?admin=true&active=false"
iex(10)> user_url(Endpoint, :index)
"http://localhost:4000/users"
iex(11)>

こんな感じで、URLやパスを出力させて試すことができます。

_url機能は、環境ごとに設定された構成パラメータから、完全なURLを構築するために
必要なホスト、ポート、プロキシポートおよびSSLの情報を取得できるもの。

4.4
PathHelpersのおかげでこんなことができます。(紹介だけ)
こんな感じで簡単に埋め込めるとのこと。

<a href="<%= page_path(@conn, :index) %>">To the Welcome Page!</a>

詳しくはViewのガイドを見てくれと・・・つまりこの記事を書いているときにはまだやっていない。
だから紹介だけしかできないw

5.おまけ

おまけなので適当・・・

5.1
特定のパスが含まれている時だけルーティングを変えたい?
としたらこんな感じにするのだ!!

つまりは、scope部分の分割。

以下の記述に対して・・・/adminのパスが含まれる時はルーティング先を変えたい。
resources "/reviews", ReviewController

こんな感じになる。
scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  resources "/reviews", ReviewController
end

scope "/admin", as: :admin do
  resources "/reviews", HelloPhoenix.Admin.ReviewController
end

5.2
5.1に続く形の内容・・・
/adminに複数行の記述をしたい場合は以下のようになる。

scope "/admin", as: :admin do
  pipe_through :browser
  
  resources "/images", HelloPhoenix.Admin.ImageController
  resources "/reviews", HelloPhoenix.Admin.ReviewController
  resources "/users", HelloPhoenix.Admin.UserController
end

冗長性とミスをなくすため以下のように書き換えることもできる。
scope "/admin", HelloPhoenix.Admin, as: :admin do
  pipe_through :browser
  
  resources "/images",  ImageController
  resources "/reviews", ReviewController
  resources "/users",   UserController
end

5.3
scopeをネストさせたい?
ならば、こんな形で記述することができる。

scope "/api", HelloPhoenix.Api, as: :api do
  pipe_through :api
  
  scope "/v1", V1, as: :v1 do
    resources "/images",  ImageController
    resources "/reviews", ReviewController
    resources "/users",   UserController
  end
end

5.4
それぞれ、mix phoenix.routesで出力結果を見てみよう!!

5.5
Phoenixアプリケーションにページを追加してみる。(その2)で作った
HelloControllerのルーティング先、そのスコープを分割してみた。

これが、
----
scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  get "/hello", HelloController, :index
  get "/hello/:messenger", HelloController, :show
end
----

こうなった。
----
scope "/", HelloPhoenix do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
end

scope "/hello", HelloPhoenix do
  pipe_through :browser

  get "", HelloController, :index
  get "/:messenger", HelloController, :show
end
----

Pipelines、Nested Resources、Scoped Routes、The Endpoint Plugs...etc
いっぱい分からないことがあるよ~
誰か日本語に翻訳されている方いないかな?(切実)
これについては、俺がやる!!って言えない・・・orz

英語ドキュメントを見ながらプログラムならいいんだよ。デバッグ/実行すれば何となく分かるし・・・
機能を英語で説明は・・・うん、俺には急に難易度が上がる。

追記(2015/06/06-16:23)
Channel Routesについて続きを書きました。
続!Phoenixのルーティング(Router)について分かったこと

以上!!

以下、参考にさせて頂いたサイト様

管理人の独り言~
この記事役に立つのか・・・?
間違ってる可能性を考えると、人様の目に付くところにアップするべきではないのかもしれない・・・
そんな思いがあります。

他にもまだ色々機能があったんですけど、、これだけしか分からなかったorz
本当に自分の亀の歩みのような成長速度には辟易します・・・
もっとドーンと成長できないですかね?www

Railsライクなので、Railsと似たような機能内容ですね。
記法や設定方法が異なるだけの気がします。
なので、Railsのルーティングは参考になります。
参考までに・・・
http://railsguides.jp/routing.html

人気の投稿