LoginSignup
8
2

More than 3 years have passed since last update.

【Rails】link_toのxxx_pathが長い時はpolymorphic_pathを使うと綺麗に書けるお話

Last updated at Posted at 2021-03-01

Railsにはよく使うものとしてlink_tobutton_toがあります。これらはリンクやボタンを生成するヘルパーです。

更に、遷移先のURLやpathを指定することが出来て、以下のように書けます。

<%= link_to '詳細へ', user_path(user.id) %>

では、URLのネストをした場合、xxx_pathはどうなるでしょうか?

例えば、ユーザーは記事を投稿でき、その記事たちをお気に入りに追加できる機能があったとします。

ルーティングはこちら

routes.rb
Rails.application.routes.draw do
  # ユーザーは記事を投稿できる
  resources :users do
    resources :articles do
      # 記事をお気に入りすることができる
      resources :favorites
    end
  end
end

rails routesを叩いてxxx_pathの部分を見てみましょう。

お気に入りの新規保存に使えるであろうfavorites#createはuser_article_favoritesになってます。
これはまだマシですが、もっとネストされたら長くなり、xxx_pathの部分が分かり辛くなるでしょう。

$ rails routes

user_article_favorites     GET    /users/:user_id/articles/:article_id/favorites(.:format)          favorites#index
                           POST   /users/:user_id/articles/:article_id/favorites(.:format)          favorites#create
new_user_article_favorite  GET    /users/:user_id/articles/:article_id/favorites/new(.:format)      favorites#new
edit_user_article_favorite GET    /users/:user_id/articles/:article_id/favorites/:id/edit(.:format) favorites#edit
user_article_favorite      GET    /users/:user_id/articles/:article_id/favorites/:id(.:format)      favorites#show
                           PATCH  /users/:user_id/articles/:article_id/favorites/:id(.:format)      favorites#update
                           PUT    /users/:user_id/articles/:article_id/favorites/:id(.:format)       favorites#update
                           DELETE /users/:user_id/articles/:article_id/favorites/:id(.:format)       favorites#destroy

本題(polymophic_path)を使おう!

Railsにはモデルから生成されたインスタンスに対して、ルーティングをスマートに書ける方法が提供されています。

公式ドキュメントはこちら

結論から言うと、こう書いていたものが、

# user    = User.find(1)
# article = Article.find(1)

<%= button_to 'お気に入りする', user_article_favorites_path(user.id, article.id), method: :post %>

こう書けます

<%= link_to 'お気に入りする', polymorphic_path([user, article, :favorites]), method: :post %>

何をしているかと言うと、polymorphic_pathの引数においたモデルインスタンスを元にリンクを生成してくれています。
今回の場合 users/1/articles/1/favoritesが生成されています。

ポイントは以下の3つです。

  • 基本的に引数にはModelのインスタンスを置く
  • 引数を複数置きたい場合は配列で囲む
  • インスタンスの生成が行われていない場合は、:favoritesのようにシンボル型で引数に置く

今回の例よりさらに複雑になったpathであれば可読性はさらに向上すると思います。
(逆にusers_pathといった短いものにpolymorphic_pathを使うと変に見えるかもしれません。)

polymorphic_pathの応用

先ほどとは別にnewアクションやeditアクションへのリンクを生成したい場合は以下のように書くこともできます。

# user    = User.find(1)
# article = Article.find(1)

<%= link_to '編集へ', edit_polymorphic_path([user, article ]) %>

<%= link_to '新規作成へ', new_polymorphic_path([user, article ]) %>

edit_polymorphic_path([user, article ]) の場合、users/1/articles/1/editのようなリンクが生成されます。

まとめ

RailsにはDRYの法則に則ったヘルパーやメソッドがたくさん用意されています。
今回扱ったpolymorphic_pathは長くなりがちなpathの記述を簡潔に書くことができます。
ぜひお試しください!

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2