どうもこんにちは。
今回は、Railsで開発を行っていたときに1時間くらい沼った問題についてお話します。
機能名は、サンプルを使用しています。(その方が分かりやすいと思うので。)
何をしようとしていたか
とある機能の「複製」機能を開発しているとき、以下のようにルーティング・コントローラ・ビューを定義しました。
resources :examples do
collection do
get 'before_copy'
end
end
class ExamplesController < ApplicationController
def before_copy
copy_source_id = params[:id]
before_copy_example = Example.find(copy_source_id)
@example = before_copy_example.dup # コピー
end
end
app
|- views
|- examples
|- index.html.erb
|- new.html.erb
|- show.html.erb
|- edit.html.erb
|- before_copy.html.erb
|- _form.html.erb
|- _detail.html.erb
上記のように実装した段階で、/examples/before_copy?id=#{example_id}
のようにアクセスしました。
出てきたエラー
そうしたらターミナルの実行ログに以下のエラーが出てきました。
web-1 | NoMethodError: undefined method `original_exception' for #<ActionView::Template::Error: No route matches {:action=>"show", :controller=>"examples", :id=>nil}, missing required keys: [:id]>
web-1 | from /usr/local/bundle/gems/web-console-2.3.0/lib/web_console/extensions.rb:16:in `block in render_exception_with_web_console'
web-1 | from <internal:kernel>:90:in `tap'
web-1 | from /usr/local/bundle/gems/web-console-2.3.0/lib/web_console/extensions.rb:3:in `render_exception_with_web_console'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/debug_exceptions.rb:39:in `rescue in call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/debug_exceptions.rb:26:in `call'
web-1 | from /usr/local/bundle/gems/web-console-2.3.0/lib/web_console/middleware.rb:20:in `block in call'
web-1 | from /usr/local/bundle/gems/web-console-2.3.0/lib/web_console/middleware.rb:18:in `catch'
web-1 | from /usr/local/bundle/gems/web-console-2.3.0/lib/web_console/middleware.rb:18:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/show_exceptions.rb:26:in `call'
web-1 | from /usr/local/bundle/gems/railties-7.0.5/lib/rails/rack/logger.rb:40:in `call_app'
web-1 | from /usr/local/bundle/gems/railties-7.0.5/lib/rails/rack/logger.rb:25:in `block in call'
web-1 | from /usr/local/bundle/gems/activesupport-7.0.5/lib/active_support/tagged_logging.rb:99:in `block in tagged'
web-1 | from /usr/local/bundle/gems/activesupport-7.0.5/lib/active_support/tagged_logging.rb:37:in `tagged'
web-1 | from /usr/local/bundle/gems/activesupport-7.0.5/lib/active_support/tagged_logging.rb:99:in `tagged'
web-1 | from /usr/local/bundle/gems/railties-7.0.5/lib/rails/rack/logger.rb:25:in `call'
web-1 | from /usr/local/bundle/gems/sprockets-rails-3.4.2/lib/sprockets/rails/quiet_assets.rb:13:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/remote_ip.rb:93:in `call'
web-1 | from /usr/local/bundle/gems/request_store-1.7.0/lib/request_store/middleware.rb:19:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/request_id.rb:26:in `call'
web-1 | from /usr/local/bundle/gems/rack-2.2.9/lib/rack/method_override.rb:24:in `call'
web-1 | from /usr/local/bundle/gems/rack-2.2.9/lib/rack/runtime.rb:22:in `call'
web-1 | from /usr/local/bundle/gems/activesupport-7.0.5/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/server_timing.rb:61:in `block in call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/server_timing.rb:26:in `collect_events'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/server_timing.rb:60:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/executor.rb:14:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/static.rb:23:in `call'
web-1 | from /usr/local/bundle/gems/rack-2.2.9/lib/rack/sendfile.rb:110:in `call'
web-1 | from /usr/local/bundle/gems/actionpack-7.0.5/lib/action_dispatch/middleware/host_authorization.rb:137:in `call'
web-1 | from /usr/local/bundle/gems/railties-7.0.5/lib/rails/engine.rb:530:in `call'
web-1 | from /usr/local/bundle/gems/rack-2.2.9/lib/rack/handler/webrick.rb:95:in `service'
web-1 | from /usr/local/bundle/gems/webrick-1.8.1/lib/webrick/httpserver.rb:140:in `service'
web-1 | from /usr/local/bundle/gems/webrick-1.8.1/lib/webrick/httpserver.rb:96:in `run'
web-1 | from /usr/local/bundle/gems/webrick-1.8.1/lib/webrick/server.rb:310:in `block in start_thread'
このログを見た時にこう思うはずです。
「ルーティング定義ミスった??」
なので、before_copy
をmember
として定義してみたり、resources
の外で定義してみたりしましたが、全て空振り...。
それもそのはず。最終的な結論として、他の箇所でエラーが発生していたのだから。
ルーティングエラーじゃないならどこ?
最初から、log/development.log
を確認すべきでした。
このログファイルには、ターミナルの実行ログ以外の情報も記載されています。
実際に記載されていたログがこちら。
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"examples", :id=>nil }, missing required keys: [:id]):
295: }, title: "削除確認", class: "btn btn-danger mr-10"
296: - if permission_allow?('examples', 'write')
297: = f.submit class:"btn btn-primary mr-10"
298: = link_to t('helpers.button.cancel'), examples_form_cancel_link(@example), class: "btn btn-default"
app/helpers/examples_helper.rb:13:in `examples_form_cancel_link'
app/views/examples/_form.html.slim:298
app/views/examples/_form.html.slim:1
app/views/examples/before_copy.html.slim:18
エラーはActionView::Template::Error (No route matches {:action=>"show", :controller=>"examples", :id=>nil }, missing required keys: [:id])
ですが、ルーティングの定義ミスだと断定するには早かったようでした。
実際にexamples_form_cancel_link
ヘルパーメソッドを確認してみたら、詳細画面(show
)へ遷移するために必要なid
が渡されていなかったため、エラーが起きていたようでした。
結論 & まとめ & 伝えたいこと
エラーが出てきた時は、log/development.log
を確認すべき!!
ターミナルの実行ログだけでは足りません!!
以上