为属于不同模型的模型创建独立表单?

时间:2015-07-20 21:40:47

标签: ruby-on-rails forms

所以我有两个模型RoomReservation

Room对象事先由拥有房间并存储在数据库中的人创建。

我想让其他用户稍后在 belongs_to 那个特定的房间创建预订(在不同的页面和完全独立的表单上),这样当我想拉出一个列表时对于那个房间的预订,我可以简单地做@room.reservations之类的事情。

我希望在RoomsController中创建房间,并在ReservationsController中创建预订。

不幸的是,我似乎无法弄清楚如何使用" Rails方式"。我想出的最好的是:

# .../rooms/new
= form_for @room, room_path do |f|
    # Form that creates a room

# .../reservations/new
= form_for @reservation, reservation_path do |f|
    # Form that creates a reservation

但是当我以这种方式这样做时,我无法(至少我知道)在ReservationsController中引用特定列表。

class ReservationsController < ApplicationController
    # What I want to do:
    @listing = Listing.new(params[:id])   # no way of getting Listing's id
    @reservation = @listing.reservations.build(reservation_params)

    # etc...

我认为我可以将其作为隐藏字段添加到reservations表单中,但我没有办法验证它。我通过填写表单然后在Chrome的Inspect Element中更改隐藏的输入字段的params [:id]值来测试它,当然这会将其发布到不同的房间,这是不可取的。

我现在不知道这样做了:

# I ended up having to create a "reserve" action in the listings controller

= form_for @listing, :url => { :controller => "listings", :action => "reserve" } do |f|
    f.fields_for :reservation do |r|
        # All the fields to create a reservation here...

这根本不是我想要的。我希望能够使用我的ReservationsController

我如何实现这一点?

1 个答案:

答案 0 :(得分:1)

使用嵌套路线:

resources :rooms, shallow: true do
  resources :reservations
end

这会在房间的背景下嵌套预订的“收集路线”。

              Prefix Verb   URI Pattern                                Controller#Action
   room_reservations GET    /rooms/:room_id/reservations(.:format)     reservations#index
                     POST   /rooms/:room_id/reservations(.:format)     reservations#create
new_room_reservation GET    /rooms/:room_id/reservations/new(.:format) reservations#new
    edit_reservation GET    /reservations/:id/edit(.:format)           reservations#edit
         reservation GET    /reservations/:id(.:format)                reservations#show
                     PATCH  /reservations/:id(.:format)                reservations#update
                     PUT    /reservations/:id(.:format)                reservations#update
                     DELETE /reservations/:id(.:format)                reservations#destroy
               rooms GET    /rooms(.:format)                           rooms#index
                     POST   /rooms(.:format)                           rooms#create
            new_room GET    /rooms/new(.:format)                       rooms#new
           edit_room GET    /rooms/:id/edit(.:format)                  rooms#edit
                room GET    /rooms/:id(.:format)                       rooms#show
                     PATCH  /rooms/:id(.:format)                       rooms#update
                     PUT    /rooms/:id(.:format)                       rooms#update
                     DELETE /rooms/:id(.:format)                       rooms#destroy

然后,您需要更改您的ReservationsController以在创建预订时使用params[:room_id]查找房间:

class ReservationsController < ApplicationController
  before_action :set_reservation, only: [:show, :edit, :update, :destroy]
  before_action :set_room, only: [:new, :create]

  # GET /rooms/:room_id/reservations
  def index
    @room = Room.includes(:reservations).find(params[:room_id])
    @reservations = @room.reservations.all
  end

  # GET /rooms/:room_id/reservations/new
  def new
    @reservation = @room.reservations.new
  end

  # POST /rooms/:room_id/reservations
  def create
    @reservation = @room.reservations.new(reservation_params)

    if @reservation.save
      redirect_to @reservation, notice: 'Reservation was successfully created.'
    else
      render :new
    end
  end

  # ... The rest of the controller actions

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_reservation
      @reservation = Reservation.find(params[:id])
    end

    def set_room
      @room.find(params[:room_id])
    end

    # Only allow a trusted parameter "white list" through.
    def reservation_params
      params.require(:reservation).permit(:room_id, :starts_at, :ends_at)
    end
end

您需要稍微更改表单,以便发布到/rooms/:room_id/

= form_for([@room, @reservation]) do |f|
   # ... fields go here

由于我们从请求网址获取房间ID,因此无需在表单中包含房间ID。