16
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails:ネストしたルーティングのパスヘルパーが長えよ

Last updated at Posted at 2016-12-21

以下のようなネストしたルーティングを考える。

config/routes.rb
resources :publishers do
  resources :books
end

んで,例えば books の一覧ページに「修正」のリンクを置くのに,ビューで

link_to "修正", edit_publisher_book_path(@publisher, @book)

とかって書くことになる。メソッド名が長えよ。

いやまあ,上の例だとモデル名が Publisher だの Book だの短いからまだかわいい。
モデル名が長かったり,namespace 使ってたりすると,

link_to "修正", edit_admin_counterpart_favorite_item_path(@counterpart, @favorite_item)

とかワケわからん。

モデルの CRUD に使うパスなんだからモデルに言われせればいいんじゃね?

ただ,モデルに直接やらせるのはおかしいので,デコレーターに定義することにする。

ActiveDecorator を使った場合,

book_decorator.rb
module BookDecorator
  def edit_path
    edit_publisher_book_path(publisher, self)
  end
end

みたいにする。(publisher は変数ではなく selfpublisher メソッドを呼び出してる)

これで,

link_to "修正", @book.edit_path

と書ける。

同じようにして,

book_decorator.rb
module BookDecorator
  def path
    publisher_book_path(publisher, self)
  end
end
publisher_decorator.rb
module PublisherDecorator
  def new_book_path
    new_publisher_book_path(self)
  end

  def books_path
    publisher_books_path(self)
  end
end

とかも定義しておく。

ビューがスッキリする。

ただ,こういうやり方がよい流儀なのかどうか,よく分からない。
「てめえの Rails は〇〇じゃねえ!」とか叱ってくれ。

コントローラーで使う(2019-06-18 追記)

パスヘルパーはコントローラーでも多用する。

例えば特定の Publisher の Book を create したり update したりしたあと,

redirect_to publisher_book_path(@publisher, @book)

みたいに,その書籍のページにリダイレクトする,ということはよくある。
こういうとき

redirect_to @book.path

と書ければよいのだが,そういうわけにはいかない。
ビューで @book.path と書けたのは,ActiveDecorator が裏で @book をデコレートしてくれていたからで,この機構はビューに持ち込まれるインスタンス変数にしか働かない。

手動でデコレートするには

ActiveDecorator::Decorator.instance.decorate(@book)

とすればよい。
そこで,ApplicationRecord

app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
  # 中略

  def decorate
    ActiveDecorator::Decorator.instance.decorate self
  end
end

と書いておけば,コントローラーで

redirect_to @book.decorate.path

と書ける。

もちろん,コントローラー以外の場所でも .decorate を使うことができる。
ビューの中で自動デコレートが効かない場合(それは良いプログラミングスタイルではないかもしれないが)にも役立つ。

2021-01-26 追記

何たる不覚。ActiveDecorator は,デコレーターをモジュールとして定義するのに,間違ってクラスにしてた。
投稿から 4 年も経って気づいたので,今さらだが直した。

16
23
1

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
16
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?