2015-07-20 58 views
1

所以,我有两个型号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形式的隐藏字段,但我没有办法验证它。我测试了通过填写表格,然后改变所述隐藏的输入字段的PARAMS [:ID]在Chrome的值检查元素,这当然将其发布到不同的室,这是不期望的。

我现在坚持这样做:

# 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

使用嵌套的路线:

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 

因为我们从请求url中获取它,所以没有必要在表单中包含房间ID。

+0

请注意,我用'Room',既然你是不是真正清楚'Listing'意味着你的应用程序。尽管如此,同样的原则也适用。 – max

+0

对不起,我的意思是“房间”,而不是“上市”!我要给这个提示一下,看看它是如何实现的,但只要看看它,我已经可以告诉我这对我来说可能是正确的答案。 –

+0

这是我用来为答案生成代码的演示Rails应用程序:https:// github。COM/maxcal /沙箱/树/ 31526836 – max

相关问题