Reputation: 120
I'm trying to call some ActiveRecord methods in OrdersController#new action. I've tested the code in Rails Console and it works the way I intended. But in the controller action it does not produce the same
order has_many cart_items
cart has_many cart_items
cart_items belong_to order cart_items
belong_to cart
cart_items belong_to product
product has_many cart_items
def new
@order.new
@order.cart_items = current_cart.cart_items
@order.save
current_cart.cart_items.destroy_all
end
Now current_cart is an application_controller method that checks if the current user has a shopping cart. If it does it pulls that cart from the database and if the user does not then it creates a new cart for the user. What I am trying to do here is when the user finalizes their order I'm trying to transfer the cart_items from current_cart to orders then clear the shopping cart.
When I do this in rails console, it gives me what I want. Order with cart_items that were in current_cart, and after I run destroy_all on the cart I have an empty active record association array.
When I test this in my controller both Order and Cart return an empty active association array.
What is going on here?
#application controller method of finding current_users cart
def current_cart
# if user is logged in
if current_user
@user = current_user
# checking user to see if account is confirmed and verified
if @user.confirmed_at != nil
# checking if user already has cart in cart database
if Cart.find_by(users_id: @user.id) != nil
# find a row in the database where users_id: equal to @user.id
# where clause does not work here
cart = Cart.find_by(users_id: @user.id)
session[:cart_id] = cart.id
cart.save
#establish Cart session cart for user
Cart.find(session[:cart_id])
else
# create a new Cart Object for user.assign current_user's id to cart object
cart = Cart.new
cart.users_id = @user.id
# save it to get cart id assign session[:cart_id] == cart.id
cart.save
session[:cart_id] = cart.id
end
end
end
end
class CartItemsController < ApplicationController
before_action :set_cart_item, only: [:show, :edit, :update, :destroy]
# scope for most_recent and subtotal
# find out if rails sorts on update column cuz this is annoying.
def create
# grabbing cart from application controller current_cart method
@cart = current_cart
# session[:cart_id] = @cart.id
# individual product items get added to cart item and added to cart and saved
@cart_item = @cart.cart_items.build(cart_item_params)
@cart.save
end
def update
@cart = current_cart
# finding cart_items by cart_id
@cart_item = @cart.cart_items.find(params[:id])
# @cart_items.order(:id)
@cart_item.update_attributes(cart_item_params)
@cart_items = @cart.cart_items.order(:id)
# redirect 'cart_show_path'
@cart.save
end
def destroy
@cart = current_cart
@cart_item = @cart.cart_items.find(params[:id])
@cart_item.destroy
@cart_items = @cart.cart_items
@cart.save
end
private
def set_cart_item
@cart_item = CartItem.find(params[:id])
end
def cart_item_params
params.require(:cart_item).permit(:cart_id, :product_id, :unit_price, :quantity, :total_price)
end
end
Upvotes: 0
Views: 149
Reputation: 120
Alright, figured it out.
I was using @order.save which was not processing the error message!!!!!!!! After @order.save! it gave me the validation error in another model. I commented that out and it worked.
I iterated current.cart_items and assigned the cart_id to nil and order_id to @order.id essentially clearing the cart and "transferring" the items over.
I couldn't figure out a way using destroy_all though. I think this is impossible like @Sri said.
Thanks alot!
So the end code was this:
@order = Order.create!(users_id: current_cart.users_id)
current_cart.cart_items.each do |item|
item.order_id = @order.id
item.save!
end
if @order.save
current_cart.cart_items.each do |item|
item.cart_id = nil
item.save!
end
Upvotes: 0
Reputation: 2520
When you say you are transferring the cart_items
from current_cart
you are passing on the objects, you are not creating new cart_items
(which means the database ids are same) and when you do current_cart.cart_items.destroy_all
it is deleting them from the database. See ActiveRecord::Relation#destroy_all
For you use case, its enough if you just do
def new
@order.new
@order.cart_items = current_cart.cart_items
@order.save
current_cart.cart_items = []
end
Upvotes: 2