Using after_create to update a cart's order_id

224 views Asked by At

First, I have a cart stored in a session. The carts contain line items(products). The checkout button leads to a Order.new form with the cart_id passed to the new order(cart has_one order, order belongs_to cart).

Hopefully so far so good.

The cart params contains an order_id, that initially is nil, until the user hits the checkout button. When the order is created, the order_id in the cart is still nil. How can I use an after_create on the order model to update the cart to now have a valid order_id?

I have a current_cart method in my application controller, so I have access to current_cart in all my controllers, but I can't access it in the model -> as it is stored in a session and I've heard I don't want to be accessing sessions in the model anyway.

How one one recommend doing this?

I'll show some code in case my description wasn't clear.

orders_controller.rb

def create
  @cart = current_cart
  @order = @cart.build_order(order_params)
  if @order.save
    redirect_to @order, notice: "The order has been successfully created.  Below are your shipping options."
  else
    render action: "new"
  end
end

rails console

>> @order.cart.order_id
=> nil

Does it even really matter? Maybe I'm being paranoid, but I think it would be good practice to have access to the order_id from the cart as well as the cart_id from the order.

Thanks all, Pat

1

There are 1 answers

4
Patrick Oscity On BEST ANSWER

You do not need to store the order_id in both directions, in fact you are probably creating more problems than you are hoping to solve with this design. For example, you will have to keep the value up to date in both directions, either when the order's cart changes or the other way around.

Rails is smart enough by itself to figure out which record is associated with which, even without an order_id on the Cart model:

cart = Cart.last
cart.order
#=> #<Order ...>

order = Order.last
order.cart
#=> #<Cart ...>

I also want to point out that you probably do not even need to persist Cart to the database, since it only makes sense in the context of a single browser session. You could instead design it as a plain old Ruby object (just a class, not inheriting from ActiveRecord::Base) and further simplify your design that way.