【问题标题】:ActionController::UrlGenerationError - missing required keysActionController::UrlGenerationError - 缺少必需的键
【发布时间】:2020-08-18 17:49:54
【问题描述】:

我是 Rails 新手,正在尝试构建我的第一个 MVC 应用程序。我正在尝试创建链接文件路径并收到此错误消息 -

Pages#my_profile 中的 ActionController::UrlGenerationError 没有路线匹配 {:action=>"show", :car_id=>10, :controller=>"bookings"},缺少必需的键:[:id]

这是我在视图中使用的代码

  <%= link_to booking.car.make, car_booking_path(booking[:id])%></h2>

当我在 Rails 控制台中输入预订时,我可以访问以下哈希

#

所以我不确定为什么,当 booking[:id] 被传递时,它没有被选中。

我的路线是

car_booking GET /cars/:car_id/bookings/:id(.:format) bookings#show

有人知道我缺少什么吗? 任何帮助将不胜感激。

【问题讨论】:

  • 请注意,您的路线需要两个变量::car_id 和 :id。您视图中的路径仅提供预订的 :id。路径应该是car_booking_path(booking[:car_id], booking[:id])
  • @dbugger [booking.car, booking] 而不是 car_booking_path(booking[:car_id], booking[:id]) 为您节省了 26 次键盘敲击...

标签: ruby-on-rails


【解决方案1】:

试试:

<% current_user.bookings.each do |booking| %>
  <%= link_to booking.car.make, [booking.car, booking] %></h2>
<% end %>

看,你有一个嵌套路由:

car_booking GET /cars/:car_id/bookings/:id(.:format) bookings#show

需要car_idid。您只传递了一个值booking[:id],它位于第一个位置,因此它被解释为car_id(尽管它实际上是booking.id)。您的参数中没有第二个值,因此您会收到 missing required keys: [:id] 消息。

请注意,如果您使用shallow nesting,则如下所示:

Rails.application.routes.draw do 

  ...

  resources :cars do 
    resources :bookings, shallow: true
  end

  ...

end

那么你就这样做:

<% current_user.bookings.each do |booking| %>
  <%= link_to booking.car.make, booking_path(booking)%></h2>
<% end %>    

另请注意,您通常可以使用booking_path(booking) 而不是booking_path(booking.id)。其实如docs中所说,可以使用精髓:

<% current_user.bookings.each do |booking| %>
  <%= link_to booking.car.make, booking %></h2>
<% end %>

如果你不想使用浅嵌套,你可以这样做:

<% current_user.bookings.each do |booking| %>
  <%= link_to booking.car.make, [booking.car, booking] %></h2>
<% end %>

...并且,正如 in the docs 所讨论的那样,Rails 将推断出 car_booking_path 助手。

在您的问题中,您说您可以访问以下哈希:

#<Booking id: 10, start_date: "2020-08-18", end_date: "2020-08-19", status: nil, user_id: 5, car_id: 5, created_at: "2020-08-18 17:34:41", updated_at: "2020-08-18 17:34:41">

仅供参考,这不是哈希。这是从ActiveRecord::Base 继承的Booking 类的一个实例。要从该实例获取id,请执行booking.id,而不是booking[:id]

【讨论】:

  • 非常感谢,car_booking_path(booking.car, booking) 工作。现在你已经指出了这一点并且完全有道理,这真的很明显。非常感谢您抽出时间来看看
  • 尝试link_to booking.car.make, [booking.car, booking] 以获得更短的形式。另外,请投票/接受以帮助未来的搜索者。
  • 哦,还有一件事。您在那里进行了 n+1 查询,因为您执行current_user.bookings,然后对于每个booking,您执行booking.car。您可能想要急切地装载汽车以避免 n+1。
【解决方案2】:

根据路线的输出,您需要传递两个参数 id 和 car_id。 试试下面的:

<%= link_to booking.car.make, car_booking_path(car_id: booking.car_id, id: booking.id)%></h2>

【讨论】:

  • car_booking_path(car_id: booking.car_id, id: booking.id) 替换为 [booking.car, booking] 可节省 34 次键盘敲击次数。
  • 刚刚想到将查询保存到汽车,因为它会触发对汽车的查询 booking.car
  • 好主意。我怀疑booking.car 将是一个缓存请求,因为booking.car 已经被booking.car.make 调用。但是,OP 以 N+1 结束,这是一个很好的观点。
  • 我认为它仍然会触发对汽车的缓存查询,除非急切加载。
  • 好点。真正重要的一点是booking.car.make 最少会导致 N+1 并且值得急切加载。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多