UrlGenerationError: No route matches missing required keys: [:id]の原因と対処法を徹底解説【Rails 初心者向け】

Ruby on Rails

missing required keys: [:id]というエラーが解決できません・・・

そんな疑問にお答えします!

結論

UrlGenerationError: No route matches missing required keys: [:id]

  • ヘルパーメソッド xxx_pathやxxx_url でパスやURLを生成するときに
  • 情報不足で生成に失敗したことを表すエラー

です。

特にヘルパーメソッドの呼び出し時に id の情報が不足しているために発生するエラーです。

例えば、rails routes で確認できるルーティングが以下のようなとき

$ rails routes
Prefix Verb   URI Pattern               Controller#Action
  book GET    /books/:id(.:format)      books#show

このルーティング情報からは以下のような情報が読み取れます。

  • パスを作るヘルパーメソッドは book_path
  • URLパターンは /books/:id であり、パラメータ :id が必要

このとき、以下のようなコードを書くと

<%= book_path %>

以下のようなエラーが発生します。

エラーメッセージには「missing required keys: [:id] 」つまり日本語にすると必要なキー :id が見つからなかった」と表示され、 id が必要だったのに指定できていないことがわかります。

これを修正には Book モデルのインスタンスを渡すのが王道です。

例えば対応するコントローラで

class BooksController < ApplicationController
  def index
    @books = Book.all
  end
end

のように Book モデルの複数のインスタンスを @books 変数にもたせているのであれば

ビューのコードでは

<% @books.each do |book| %>
  <%= link_to book.title, book_path(book) %>
<% end %>

のように、Book モデルのインスタンスが入った変数 book を book_path メソッドに引数にすればオーケーです。

どのインスタンスを渡せばいいかはその機能の仕様によるためケースバイケースですが、大切なことは

:id を URI パターンに含む場合、
ヘルパーメソッドにはその :id を持つモデルのインスタンスを渡す

ということです。

ルーティングについては以下の記事も参考にしてください。

rails routes コマンドの読み方を徹底解説

エラーの内容

エラー内容について深堀りしておきます。

エラー画面例を再掲します。

このエラーについて解説していきます。

エラー名

まず、ActionControler::UrlGenerationError はその名の通り URL を生成しようとしたときに起きるエラーです。

「URLを生成しようとしたが情報が足りなくて失敗した」という場合に発生します。

エラーメッセージ前半

No route matches {:action => “xxx”, :controller => “yyy”, … } は、

  • ヘルパーメソッドxxx_path、xxx_url を使ってパスやURLを生成しようとした
  • しかしマッチするルーティングが見つからなかった

ということを表しています。

ヘルパーメソッドが「アクション名、コントローラ名」+追加パラメータ(:id など)で対応するルーティングを探そうとするためです。

例えば、

Prefix Verb   URI Pattern               Controller#Action
  book GET    /books/:id(.:format)      books#show

のようなルーティングであれば、Prefix が book なので book_path というメソッドでパスを生成できます。

このとき book_path メソッドは、Controller#Action の列の表記(books#show)から

  • コントローラ名=books
  • アクション名=show

ということが決まります。

URI Pattern の列を見ると :id 部分が変えられる場所になっており、それも決めないとこのルーティングが一意に定まりません。

エラー例の場合は {:action => “show”, :controller => “posts”, :id => nil} のように表示されており、:id の部分が nil (=なにもない)のため、この行にはマッチしない(対応するルーティングが見つからない)ということになります。

エラーメッセージ後半

missing required keys: [:id] は埋められなかったパラメータを表しています。

この例では :id が埋められなかったということを表しています。

そのため修正方針としては :id を埋めるために何をすればいいかを考えるということになります。

修正方法

修正方法を具体的に解説します。

先述のとおり、基本はエラー発生箇所で使用しているヘルパーメソッドに引数を指定することです。

xxx_path ヘルパーメソッドの引数については以下も参照してください。

【Rails】undefined method ***_path の原因と解決のための前提知識の徹底解説【初心者向け】

No route matches {:action => アクション名、:controller => コントローラ名 } の場合 (:id =>がない場合)

No route matches に続くハッシュ表記 { … } に :id が無い場合は、そもそも id となるデータが指定されていません。

例えば以下のようなルーティングがある場合、

Prefix Verb   URI Pattern               Controller#Action
  book GET    /books/:id(.:format)      books#show

Prefix が book なので book_path というメソッドが使えます。

この book_path メソッドでは :id を特定できるデータを引数に指定する必要があります。

例えば、

<%= link_to "詳細", book_path %>

のように book_path に引数を与えなければこのエラーとなります。

これを修正するには、

<%= link_to "詳細", book_path(id: 1) %>

のようにハッシュで id の値を指定します。(1 は適当に指定しています。状況に合わせて指定しましょう。)

また、モデルのインスタンスを引数に指定することもできます。

コントローラで、

@book = Book.find(1)

のように変数にモデルのインスタンスを保持した上で、

<%= link_to "詳細", book_path(@book) %>

のようにモデルのインスタンスを _path メソッドの引数にします。

すると :id にはそのインスタンスの id 属性の値が指定されます。

(ただし find の引数 1 は適当です。実際には params などから取得した値を入れることが多いです)

見出し

:id の場合で説明していますが、別のパラメータでも同様です。

しかし、筆者が見てきた Rails 初心者が引っかかるのはほぼ :id の場合です。

正確に把握するには missing required keys: に続くメッセージでどのキーが足りないのかを確認してください。

たとえば

missing required keys: [:foo]

の場合は :foo が足りないということになります。

No route matches {:action ⇒ アクション名、:controller => コントローラ名, :id => nil } の場合 (:id =>がある場合)

No route matches に続くハッシュ表記 { … } に :id => nil という表記がある場合は、

:id に相当するデータを渡そうとしているが、そのデータが nil

ということを表しています。

例えば、今までと同様なルーティングの例では

Prefix Verb   URI Pattern               Controller#Action
  book GET    /books/:id(.:format)      books#show

わざとらしく書けばこのようなときにこのエラーとなります。

<%= link_to "詳細", book_path(id: nil)

ただしこんなふうにわざと nil を指定することはまずありません。

多くの場合は以下のような場合に発生します。

例えばコントローラで

@book = Book.new

のようにモデルクラスの新規インスタンスを @book 変数に入れた状態で

<%= link_to "詳細", book_path(@book) %>

とするとこのエラーとなります。

これは .new でインスタンスを作っただけの状態(=データベースにまだ保存されていない状態)では、まだ id が発行されておらず nil となっているためです。

そのため :id => nil を指定したことと同じ状態になっています。

link_to メソッドはパスではなくモデルクラスのインスタンスを与えることもできるため

<%= link_to "詳細", @book %>

のように @book を直接渡すこともできますが、この場合も id が nil のインスタンスを渡した場合は同じエラーが発生します。

対処としては、指定した変数に入っているモデルクラスのインスタンスは id の値があるか(=データベースに保存済みのレコードに対するインスタンスであるか)を確認しましょう。

まとめ

エラー No route matches, missing required keys: [:id] の原因と対処法について解説しました。

このエラーは

  • URI パターンに :id があるが
  • xxx_path メソッドに :id を特定できる値を渡せていない

ということを表します。

そのため対処としては

  • ハッシュで {id: 値} を渡す
  • 保存済みの(=idの値がある)モデルクラスのインスタンスを渡す

です。

基本は Rails のルーティングの基礎を理解することですので以下の記事も参考にしてください。

rails routes コマンドの読み方を徹底解説

その他の Rails エラー関連記事はこちら

タイトルとURLをコピーしました