Ruby on Rails困难的形式/关联

时间:2015-04-18 16:54:50

标签: ruby-on-rails ruby

我有一个Rails 4.2应用程序,其中包含'Rooms','Bookings'和'Extras'。

在预订时,这是一个房间,例如website.com/rooms/1/bookings/1

我有额外的东西,我希望通过复选框与该房间的预订相关联。

如何实施?我一直在阅读has_many :foo, :through => :bar关联,但我不确定这是否可行。

相关代码如下所示:

<!-- app\views\bookings\_form.html.erb -->

<%= form_for([@room, @booking]) do |f| %>
  <p>
    <%= f.label 'Select Customer:' %>
    <%= f.collection_select :user_id, User.all, :id, :customer_name %>
  </p>
  <p>
    <%= f.label 'start_time', 'Start Date and Time:' %>
    <%= f.datetime_select :start_time, { minute_step: 15 } %>
  </p>
  <p>
    <%= f.label 'length', 'Length of booking in hours:' %>
    <%= f.number_field 'length', min: 1 %>
  </p>
  <p>
    <%= f.label 'Room Price:' %>
    <%= number_to_currency @room.price, unit: "£" %>
  </p>
  <p>
    <%= f.label 'Extras:' %>
    <%= f.collection_check_boxes :extra_ids, Extra.all, :id, :extra_info %>
  </p>
  <%= f.submit 'Submit' %>
<% end %>

# app\models\booking.rb
class Booking < ActiveRecord::Base
  belongs_to :room
  belongs_to :user
  has_many :additions
  has_many :extras, :through => :additions
end

# app\models\extra.rb
class Extra < ActiveRecord::Base
  belongs_to :extracat
  has_many :additions
  has_many :bookings, :through => :additions

  def extra_info
    "#{name}"
  end
end

# This model is for the has_many through testing I tried
# app\models\addition.rb
class Addition < ActiveRecord::Base
  belongs_to :booking
  belongs_to :extra
end

# Relevant section of schema
create_table "additions", force: :cascade do |t|
  t.integer  "booking_id"
  t.integer  "extra_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "bookings", force: :cascade do |t|
  t.datetime "start_time"
  t.datetime "end_time"
  t.integer  "length"
  t.integer  "room_id"
  t.integer  "user_id"
  t.integer  "extra_id"
end

编辑 - 预订中的部分显示页面。

# app\views\bookings\show.html.erb
<% @booking.extras.each do |e| %>
  <%= e.name %>,
<% end %>

编辑 - 添加预订控制器

class BookingsController < ApplicationController
  respond_to :html, :xml, :json

  before_action :find_room

  def index
    @bookings = Booking.where("room_id = ? AND end_time >= ?", @room.id, Time.now).order(:start_time)
    respond_with @bookings
  end

  def new
    @booking = Booking.new(room_id: @room.id)
  end

  def create
    @booking =  Booking.new(params[:booking].permit(:room_id, :start_time, :length))
    @booking.room = @room
    if @booking.save
      redirect_to room_bookings_path(@room, method: :get)
    else
      render 'new'
    end
  end

  def show
    @booking = Booking.find(params[:id])
  end

  def destroy
    @booking = Booking.find(params[:id]).destroy
    if @booking.destroy
      flash[:notice] = "Booking: #{@booking.start_time.strftime('%e %b %Y %H:%M%p')} to #{@booking.end_time.strftime('%e %b %Y %H:%M%p')} deleted"
      redirect_to room_bookings_path(@room)
    else
      render 'index'
    end
  end

  def edit
    @booking = Booking.find(params[:id])
  end

  def update
    @booking = Booking.find(params[:id])
    # @booking.room = @room

    if @booking.update(params[:booking].permit(:room_id, :start_time, :length))
      flash[:notice] = 'Your booking was updated succesfully'

      if request.xhr?
        render json: {status: :success}.to_json
      else
        redirect_to resource_bookings_path(@room)
      end
    else
      render 'edit'
    end
  end

  private

  def save booking
    if @booking.save
        flash[:notice] = 'booking added'
        redirect_to room_booking_path(@room, @booking)
      else
        render 'new'
      end
  end

  def find_room
    if params[:room_id]
      @room = Room.find_by_id(params[:room_id])
    end
  end

  def booking_params
     params.require(:booking).permit(:user_id, :extra_id)
  end

end

如何将额外内容与预订相关联?到目前为止,他们没有与预订一起保存到数据库中。这是控制器问题吗?

1 个答案:

答案 0 :(得分:2)

您不允许正确使用参数 - 名称为extra_ids。此外,由于参数是一个数组,您需要允许它:

params.require(:booking).permit(:room_id, :start_time, :length, :extra_ids => [])

我个人建议在开发或测试中遇到未经许可的参数时设置动作控制器以引发错误 - 否则很容易错过日志消息