Rails

Railsの不特定ModuleやClass(Modelなど)で`_path`を使う

名前付きルーティング

Railsではpath/to/fooを表示するためにfoo_pathのような便利なメソッド(Url Helper)があります。

しかしこの機能はController、HelperとViewでしか使えません。もしmodelや自作moduleでfoo_pathを呼ぶと、下記エラーが発生します。

class Foo
  def self.show_path_1
    foo_path
  end

  def show_path_2
    foo_path
  end
end

Foo.show_path_1
# => NameError: undefined local variable or method `foo_path' for Foo:Class

foo = Foo.new
foo.show_path_2
# => NameError: undefined local variable or method `foo_path' for #<Foo:0x007fccd191b8b0>

一般的な解決法

Url HelperRails.application.routes.url_helpersより提供されていますので、下記書き方で解決できます。

Rails.application.routes.url_helpers.foo_path
# => path/to/foo

ちなみにrails consoleの場合、app.foo_pathでもつかえます。

もっと自然な書き方

pathを書くたびにRails.application.routes.url_helpersを書くのはやっぱり不自然ですね。ControllerやViewのようにfoo_pathを直接書く方法があるでしょう?

一言いうと、あります。Gem Sitemap Generatorを使う時、sitemap.rbの中でfoo_pathを書けます。

もしクラスメソッドで使いたい場合、この書き方で

class Foo
  class << self
    include Rails.application.routes.url_helpers
  end

  def self.show_path_1
    foo_path
  end
end

Foo.show_path_1
# => path/to/foo

もしインスタンスメソッドの中で使いたい場合、こちらの書き方で

class Foo
  include Rails.application.routes.url_helpers

  def show_path_2
    foo_path
  end
end

foo = Foo.new
foo.show_path_2
# => path/to/foo

参考

https://stackoverflow.com/questions/6074831/how-to-access-url-helper-from-rails-module#answer-23272893
https://qiita.com/gogotanaka/items/c931360b3f6248959f89
https://qiita.com/miyazawa_shi/items/ad587553041a8a484415