删除方法不起作用,无法使用&id =' = 15找到预订

时间:2017-03-19 23:21:47

标签: ruby-on-rails ruby model-view-controller

我创建了一个Web应用程序,用户可以在其中预订一小时的培训。我希望这个应用程序让用户删除它,如果它想要的话。当我到达unbook按钮时,它会显示一条错误消息:

  

BookingsController#destroy中的ActiveRecord :: RecordNotFound

     

找不到带有' id' = 14

的预订

我想知道为什么会发生这种情况以及如何解决这个问题,以便成功完成预订的删除。

预订管制员:

class BookingsController < ApplicationController
  before_action :load_training,  only: [:create]

  def new
    @booking = Booking.new
    @training = Training.find(params[:training_id])
    @booking.training_id
  end

  def create
    @booking = @training.bookings.build(booking_params)
    @booking.user = current_user

    if @booking.save
      flash[:success] = "Reservacion creada"
      redirect_to trainings_path
    else
      render 'new'
    end
  end

  def index
    @bookings = Booking.where(training_id: params[:training_id])
  end


  def destroy
    Booking.find(params[:id]).destroy
    flash[:success] = "Reservacion eliminada"
    redirect_to trainings_path
  end

private
  def booking_params
    params.require(:booking).permit(:id, :user_id, :training_id)
  end

  def load_training
    @training = Training.find(params[:training_id])
  end
end

训练节目:

<div class="row">
    <section>
      <h1>
HOUR: <%= @training.hour %>
      </h1>
    </section>
    <section>
      <h1>
SLOTS: <%= @training.left_slots %>
      </h1>
    </section>

    <center>
    <%= render 'bookings/booking_form' if logged_in? %>
    <%= render 'bookings/index_bookings' if logged_in? %>
    </center>

Booking_form:

<% unless current_user?(@user) %>
  <% if current_user.not_booked?(@training) %>
    <%= link_to "Book", new_training_booking_path(@training),
        class: "btn btn-primary" %>
  <% else %>
    <%= link_to "Unbook", training_booking_path(@training),
        method: :delete, data:{ confirm: 'You sure?' },
        class: "btn btn-primary" %>
    <% end %>
  <% end %>

config.rb:

Rails.application.routes.draw do

  root 'static_pages#home'
  get    '/signup',               to: 'users#new'
  get    '/contact',              to: 'static_pages#contact'
  get    '/about',                to: 'static_pages#about'
  get    '/login',                to: 'sessions#new'
  post   '/login',                to: 'sessions#create'
  delete '/logout',               to: 'sessions#destroy'


  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :users
  resources :trainings do
    resources :bookings
  end
end

培训模式:

class Training < ApplicationRecord
  has_many :users, through: :bookings
  has_many :bookings

  def can_book?
    bookings.count < slots
  end

  def left_slots
    slots - bookings.count
  end
end

预订模式:

class Booking < ApplicationRecord
  belongs_to :user
  belongs_to :training
  validates :user_id, presence: true
  validates :training_id, presence: true
  validate :training_not_full?, on: :create



private

  def training_not_full?
    errors.add(:base, :full, message: "Full training") unless training.can_book?
  end

end

用户模型:

class User < ApplicationRecord

  has_many :trainings, through: :bookings
  has_many :bookings

    def not_booked?(training)
      bookings.where(training: training).none?
    end
end

由于

3 个答案:

答案 0 :(得分:2)

它是一种嵌套路线。您需要指定培训和预订才能删除。而不是......

<%= link_to "Unbook", training_booking_path(@training),
    method: :delete, data:{ confirm: 'You sure?' },
    class: "btn btn-primary" %>

做...

<%= link_to "Unbook", training_booking_path(@training, @training.bookings.where(user: current_user).first,
    method: :delete, data:{ confirm: 'You sure?' },
    class: "btn btn-primary" %>

答案 1 :(得分:0)

在您的预订表单中,您只会发送培训的ID,而不是预订。 因此,它试图删除具有训练ID的书。您应该发送培训的ID和预订。

如果你rake routes,你会有这样的路线:

DELETE /trainings/:training_id/bookings/:id(.:format)      bookings#destroy

这需要培训ID和预订ID。

<%= link_to "Unbook", training_booking_path(@training, <the booking object>),

如果培训有多次预订,您必须决定系统如何决定要删除的预订。 @ training.bookings.first,很可能会返回第一个预订。

答案 2 :(得分:0)

由于booking是嵌套资源(取决于training),因此您需要将@training@booking的ID传递给网址助手。

<%= link_to "Unbook", training_booking_path(@training), method: :delete %>

在上面的代码段中,网址应为training_booking_path(@training, @booking),或者您甚至可以将其简化为

<%= link_to "Unbook", [@training, @booking], method: :delete %>

(为简洁起见,dataclass选项已被排除。

确保在负责显示链接的视图的控制器操作中定义了@booking

Rails会根据DELETE选项和目标/trainings/#{@training.id}/bookings/#{@booking.id}

推断您是否尝试向method: :delete发送[@training, @booking]个请求

您可以通过运行rake routes找到确切的路径,您应该找到以下条目:

DELETE /trainings/:training_id/bookings/:id bookings#destroy

因此,在destroy方法中,您可以使用

找到booking
# in bookings_controller.rb

class BookingsController < ApplicationController
  before_action :set_training # you need to find the training before performing any action

  # other actions

  def destroy
    @booking = @training.bookings.find(params[:id])
    @booking.destroy
    # flash setting & redirect
  end

  private

  def set_training
    @training = Training.find(params[:training_id])
  end

要了解有关路由嵌套资源的更多信息,请阅读文档here