URL ヘルパーを含む ActiveDecorator のメソッドがテストで使えない
Q&A
Closed
解決したいこと
ActiveDecorator のデコレーターメソッドに URL ヘルパーやパスヘルパーを使うことがよくあります。
module ItemDecorator
def path
item_path(self)
end
end
上記の path のようなメソッドをテストコードで使うとき,中で使われている item_path が NoMethodError になるので,次節で述べる一工夫が必要です。
その一工夫が,active_decorator 1.4.1 では有効だったのに,1.5.0 以降は効かなくなりました。
1.5.0 以降で通用するやり方が知りたいです。
詳細
コントローラーのテストで,この ItemDecorator#path を使うとします:
require "test_helper"
class ItemsControllerTest < ActionDispatch::IntegrationTest
test "decorate" do
item = Item.create
ActiveDecorator::Decorator.instance.decorate item
assert_equal "/items/#{ item.id }", item.path
end
# 後略
このままではテストが通りません。
デコレーターで使っている item_url が NoMethodError になります。
1.4.1 までの対処方法
test/test_helper.rb に以下を追加してやります。
require "active_decorator/view_context"
ActiveDecorator::ViewContext.push Rails.application.routes.url_helpers
ActiveDecorator::ViewContext がどういう働きをしているのか,私は理解していません。
上記のコードはどこかで見て採用したはずですが既に思い出せず,いま探すこともできませんでした。
このやり方が正当なのかどうか分かりませんが,ともかくこれによってテストが通るようになります。
active_decorator 1.4.1 まではこの方法で大丈夫でした。
1.5.0 以降
その後リリースされた 1.5.0, 1.5.1 では再び NoMethodError が出るようになりました。
active_decorator 1.5.0 では ViewContext まわりで 大きな変更が入った ので,そのせいかと思いますが,直接なにが悪いのか分かりませんでした。
もう少し試したこと
ActiveDecorator::ViewContext.push Rails.application.routes.url_helpers
を test_helper.rb ではなく,個々のテストの中に入れて,
class ItemsControllerTest < ActionDispatch::IntegrationTest
test "decorate" do
# ↓ここに追加
ActiveDecorator::ViewContext.push Rails.application.routes.url_helpers
item = Item.create
ActiveDecorator::Decorator.instance.decorate item
assert_equal "/items/#{ item.id }", item.path
end
# 後略
のようにすれば,テストが通るようになりました。
しかし,一箇所に書けば済む方法はないものでしょうか。
各種バージョン
- ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [arm64-darwin25]
- Rails 7.2.3
- minitest 5.27.0
- active_decorator 1.5.1 と 1.4.1 を対照