I have seen this error, I understand the problem or so I hope I do, the problem being my order_items are saving before an Order Id has been created. The problem of being a nube is having a clue about the problem but not idea about how to implement the solution, your patience is appreciated.
The error I am getting.
ActiveRecord::RecordNotSaved (You cannot call create unless the parent is saved):
app/models/shopping_bag.rb:22:in
add_item' app/controllers/order_items_controller.rb:10:increate'
My OrderItems controller
class OrderItemsController < ApplicationController
def index
@items = current_bag.order.items
end
def create
current_bag.add_item(
book_id: params[:book_id],
quantity: params[:quantity]
)
redirect_to bag_path
end
def destroy
current_bag.remove_item(id: params[:id])
redirect_to bag_path
end
end
My Orders controller
class OrdersController < ApplicationController
before_action :authenticate_user!, except:[:index, :show]
def index
@order = Order.all
end
def new
@order = current_bag.order
end
def create
@order = current_bag.order
if @order.update_attributes(order_params.merge(status: 'open'))
session[:bag_token] = nil
redirect_to root_path
else
render new
end
end
private
def order_params
params.require(:order).permit(:sub_total, :status, :user_id)
end
end
My shopping bag Model
class ShoppingBag
delegate :sub_total, to: :order
def initialize(token:)
@token = token
end
def order
@order ||= Order.find_or_create_by(token: @token, status: 'bag') do | order|
order.sub_total = 0
end
end
def items_count
order.items.sum(:quantity)
end
def add_item(book_id:, quantity: 1)
book = Book.find(book_id)
order_item = order.items.find_or_create_by(
book_id: book_id
)
order_item.price = book.price
order_item.quantity = quantity
ActiveRecord::Base.transaction do
order_item.save
update_sub_total!
end
end
def remove_item(id:)
ActiveRecord::Base.transaction do
order.items.destroy(id)
update_sub_total!
end
end
private
def update_sub_total!
order.sub_total = order.items.sum('quantity * price')
order.save
end
end
Thank you, your time is appreciated.
From docs about find_or_create_by:
This method always returns a record, but if creation was attempted and failed due to validation errors it won’t be persisted, you get what create returns in such situation.
Probably this is the situation - the record was not persisted in a database, but only created in memory. Looking at your code, I think you want to use a bang-version of the method (find_or_create_by!), which will raise an error in such situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With