2016-10-12 4 views
0

Ich habe ein Produkt.
Ich habe eine Bestellung.
Ich habe eine Buchung zwischen.Schienen zuerst oder initialisieren funktioniert nicht

Immer wenn ich eine Buchung vom Produkt zur Bestellung mache speichert es eine neue einmalige Buchung.

Es sollte:

  1. Speichern Sie eine neue Buchung, wenn es das erste aus diesem Produkt hergestellt.
  2. Keine neue Buchung, aber eine alte finden und überschreiben, wenn das Produkt bereits einmal gebucht wurde.
  3. Wenn das Produkt bereits in der Bestellung gebucht wurde, aber keine Änderungen vorgenommen werden, werden keine Datenbanktransaktionen durchgeführt.
def create 
    @order = current_order 
    @booking = @order.bookings.where(product_id: params[:product_id]).first_or_initialize 
    product = @booking.product 
    if @booking.new_record? 
     @booking.product_name = product.name 
     @booking.product_price = product.price 
    else 
    @booking.product_quantity = params[:product_quantity] 
    @booking.save 
    @order.sum_all_bookings 
    @order.save 
    end 

funktioniert nicht.

Folge arbeitet:

def create 
    @booking = @order.bookings.find_by(product_id: params[:booking][:product_id]) 
    if @booking 
     @booking.product_quantity = params[:booking][:product_quantity] 
     @booking.save 
    else 
     @booking = @order.bookings.new(booking_params) 
     @product = @booking.product 
     @booking.product_name = @product.name 
     @booking.product_price = @product.price 
    end 
    @order.save 
    end 

Offenbar brauchte ich die params zu packen, durch [:booking] wie in params[:booking][:product_id] hinzufügen. Jeder weiß warum?

Antwort

0

können Sie

@order.bookings.find_or_initialize_by(product_id: params[:product_id]).tap do |b| 
     # your business logic here 
    end 
+0

Irgendwie kommen die Params nicht richtig durch. –

0

versuchen Duplikate sollten Sie eine Datenbankindex Beziehungen Setup richtig zu vermeiden und mit Eindeutigkeit zu gewährleisten.

class Order 
    has_many :bookings 
    has_many :products, though: :bookings 
end 

class Booking 
    belongs_to :order 
    belongs_to :product 
    validates_uniqueness_of :order_id, scope: :product_id 
end 

class Product 
    has_many :bookings 
    has_many :orders, though: :bookings 
end 

Die Validierung verhindert das Einfügen von Duplikaten auf Anwendungsebene. Es ist jedoch immer noch anfällig für Rennbedingungen.

class AddUniquenessContstraintToBooking < ActiveRecord::Migration[5.0] 
    def change 
    add_index :bookings, [:order_id, :product_id], unique: true 
    end 
end 

Der Rest von Ihnen Controller-Logik ist jedoch verworren und überkompliziert. Ich würde verschiedene Routen für update und create:

class BookingsController < ApplicationController 

    before_action :set_order, only: [:create, :index] 
    before_action :set_order, only: [:create, :index] 

    # POST /orders/:order_id/bookings 
    def create 
    @booking = @order.bookings.new(booking_params) 
    if @booking.save 
     redirect_to @order 
    else 
     render :new 
    end 
    end 

    # PATCH /bookings/:id 
    def update 
    if @booking.update(:booking_params) 
     redirect_to @order 
    else 
     render :edit 
    end 
    end 

    private 

    def set_order 
    @order = Order.find(params[:id]) 
    end 

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

    def booking_params 
    params.require(:booking) 
      .permit(:product_id) 
    end 
end 

Eine weitere Alternative ist accepts_nested_attributes zu verwenden - aber versuchen Sie es einfach zu halten.

+0

Diese Zeile schlägt immer '@ booking = @ order.bookings.find_by (product_id: params [: product_id]) 'fehl, wenn ich' if @ booking' tue. Deshalb bekomme ich zur Zeit immer ganz neue Buchungen. –

+0

Ich habe auch herausgefunden, dass die params [..] nicht funktioniert. Ich muss dafür eine separate private Funktion machen. Meine Update-Funktion ist separat, da das Update in der Reihenfolge selbst bastelt. –

+0

Ich habe es gelöst: Anscheinend musste ich die Params greifen, indem ich [: booking] wie in params [: booking] [: product_id] hinzufügte. Pass auf warum? –

Verwandte Themen