You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中BookingsController#create获取hotel_id失败报错求助

Fixing ActiveRecord::RecordNotFound in BookingsController#create

Let's resolve this issue step by step — the core problem is that your create action isn't receiving the hotel_id parameter, so Rails can't locate the associated Hotel. Here's how to fix it properly:

1. Ensure Proper Nested Routing

First, make sure your bookings routes are nested under hotels in config/routes.rb. This ensures the hotel_id is included in the URL when accessing booking actions:

resources :hotels do
  resources :bookings, only: [:new, :create] # Add other actions like :show if needed
end

This generates URLs like /hotels/:hotel_id/bookings/new (for the form) and /hotels/:hotel_id/bookings (for the POST request), which will automatically pass hotel_id in params.

2. Update the new Action to Build Associated Booking

Modify your new action to build the booking directly from the hotel object. This establishes the association upfront, so the form will automatically include the hotel_id when submitted:

def new
  @hotel = Hotel.find(params[:hotel_id])
  @booking = @hotel.bookings.new # This links the booking to the hotel immediately
  
  # Simplify room queries (no need for joins since we already have @hotel)
  room = @hotel.room # Use @hotel.rooms if Hotel has many Rooms
  @single = room.pluck(:single_bedroom_num)
  @double = room.pluck(:double_bedroom_num)
  @suite = room.pluck(:suite_room_num)
  @dormitory = room.pluck(:dormitory_room_num)
  
  # Remove the s/d/su/dor variables — they won't exist in the GET request for new
end

3. Fix the Form to Submit hotel_id

In your app/views/bookings/new.html.erb form, use the nested model syntax to ensure the hotel_id is included in the form data:

<%= form_with(model: [@hotel, @booking], local: true) do |form| %>
  # Your existing form fields (guest name, dates, room counts, etc.)
  
  # Optional: If you want to explicitly add a hidden field (though the nested model should handle this)
  <%= form.hidden_field :hotel_id, value: @hotel.id %>
  
  <%= form.submit "Book Now" %>
<% end %>

4. Update the create Action to Use the Association

Modify the create action to use the hotel's booking association, which automatically sets the hotel_id without relying on it being in the submitted params:

def create
  @hotel = Hotel.find(params[:hotel_id])
  @booking = @hotel.bookings.new(book_params) # Association sets hotel_id automatically
  
  if @booking.save
    flash[:notice] = "Booked successfully!" # Use flash[:notice] for redirects (flash.now is for renders)
    redirect_to root_path
  else
    flash.now[:alert] = "Oops, couldn't book."
    render :new
  end
end

5. Verify Strong Parameters

Your existing book_params already permits :hotel_id, which is fine — but since we're using the association to set it, you don't strictly need it in the permitted list. You can keep it or remove it; either way will work.

Why This Works

  • Nested routes ensure hotel_id is present in the request URL, so params[:hotel_id] exists in both new and create actions.
  • Building the booking from @hotel.bookings.new establishes the association, so the form includes the necessary hotel_id data (either via the nested form URL or the hidden field).
  • Using the association in create guarantees the booking is linked to the correct hotel, even if the hotel_id wasn't explicitly submitted (though it will be, thanks to the form setup).

内容的提问来源于stack exchange,提问作者Vridhi Sahu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:22:46