Railsのroutes.rb
で使用できるresolve
メソッドについて紹介します。resolve
メソッドは、polymorphic_path
やpolymorphic_url
にモデルインスタンスを渡した際に生成されるURLをカスタマイズできます。
resolveとは
Railsのビューヘルパーでは、link_to 'title', @post
のように、URLが必要とされる箇所でモデルインスタンスを直接渡すことができます。このとき、内部ではpolymorphic_path
によってURLが生成されています。resolve
を使用することで、この生成されるURLを柔軟に変更することが可能になります。
polymorphic_pathの挙動
polymorphic_path
には、主にモデルインスタンスやシンボル、またはそれらの配列を渡すことができます。
-
モデルインスタンスの場合:
persisted?
(データベースに保存済みかどうか)によって、単数形(モデルインスタンスの引数つき)または複数形のURLヘルパーが使用されます。例えば、@post
が保存済みであればpost_path(@post)
、未保存であればposts_path
が使用されます。 -
シンボルの場合: そのシンボル名に対応するURLヘルパーが使用されます。例えば、
:basket
であればbasket_path
が使用されます。 -
配列の場合: 配列の先頭から順に、中身に応じて名前を
_
で連結したURLヘルパーが組み立てられます。モデルインスタンスとシンボルが混在している場合も、上記ルールに従って処理されます(詳細は後述)。
単数リソースにおけるresolveの活用
単数リソース(例えば、resource :basket
)の場合、form_with model: @basket do |f|
のように記述すると、内部でpolymorphic_path(@basket)
が実行され、通常はbasket_path(@basket)
が呼ばれ、URLは/baskets/:id
となります。しかし、単数リソースでは/basket
というURLを期待する場合が多いです。
このような場合に、resolve
が役立ちます。以下のように定義することで、polymorphic_path(@basket)
がpolymorphic_path([:basket])
と同様に扱われるようになります1。
resolve "Basket" do
[:basket]
end
この定義により、polymorphic_path(@basket)
の内部でこの定義が参照され、シンボル:basket
からbasket_path
が組み立てられ(引数なし)、URLは/basket
となります。
URLの配列記法とネストされたリソース
polymorphic_path
には配列を渡すことができ、これはネストされたリソースや名前空間内のリソースを指す際に便利です。
-
polymorphic_path([@post, @comment])
はpost_comment_path(@post, @comment)
に相当します。 -
polymorphic_path([:admin, @post])
はadmin_post_path(@post)
に相当します。
ネストされたリソースの場合、resolve
を使って子リソースのインスタンスのみからネストされたURLを生成することができます。
resolve "Comment" do |comment|
[comment.post, comment]
end
この定義により、polymorphic_path(@comment)
は/posts/:post_id/comments/:id
というURLを生成するようになります。これにより、link_to "コメント", @comment
のように簡潔に記述することができます。
まとめ
resolve
の利用法として単数リソースのURLを調整したり、ネストされたリソースのURLを簡略化する例を挙げましたが、他にももっと複雑なURLのルールを作るときにも便利です。活用してみましょう!
References
-
要素が1つだけなので配列
[:basket]
ではなく単に:basket
でも問題ありませんが、Railsガイドやリファレンスマニュアルでは配列で記述されていることが多いため、ここではそれに倣っています。また、実際の動作はpolymorphic_url([:basket])
が呼ばれた後、パス部分だけが抜き出されます。 ↩