Search code examples
ruby-on-railsmodel-view-controllermodelshopping-cart

How to save ids to users columns


So I've built a system of products and a shopping cart in my rails app. The goal I have is to add ids of the saved products from a cart to the user model. So in my cart view page there is a list of all added products in a cart and I want to add a save button which will save those products by their ids to the columns in users table. As an example, if current_user ads three products in the cart with ids 1,2,3 and clicks on "Save" button in a cart, I want to be able to save those three ids by integers to the three columns: product_one, product_two, product_three of the current_user.

So far these are my models:

class Item < ActiveRecord::Base
    has_one :cart
end

class User < ActiveRecord::Base

  has_one :cart
  has_many :items, through: :cart 
end

class Cart < ActiveRecord::Base

  belongs_to :user
  belongs_to :item

  validates_uniqueness_of :user, scope: :item
end

My controllers:

class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :edit, :update, :destroy]

  respond_to :html, :json, :js

  def index
    @items = Item.where(availability: true)
  end 

  def show
  end 

  def new 
    @item = Item.new
  end 

  def edit
  end 

  def create
    @item = Item.new(item_params)
    @item.save
    respond_with(@item)
  end 

  def update
    @item.update(item_params)
    flash[:notice] = 'Item was successfully updated.'
    respond_with(@item)
  end 

  def destroy
    @item.destroy
    redirect_to items_url, notice: 'Item was successfully destroyed.'
  end 

  private
    def set_item
      @item = Item.find(params[:id])
    end 

    def item_params
      params.require(:item).permit(:name, :description, :availability) 
    end 
end

my cart controller:

class CartController < ApplicationController

  before_action :authenticate_user!, except: [:index]


  def add
    id = params[:id]
    if session[:cart] then
      cart = session[:cart]
    else
      session[:cart] = {}
      cart = session[:cart]
    end
    if cart[id] then
      cart[id] = cart[id] + 1
    else
      cart[id] = 1
    end
  redirect_to :action => :index
  end


  def clearCart
    session[:cart] = nil
    redirect_to :action => :index
  end






  def index
    if session[:cart] then
      @cart = session[:cart]
    else
      @cart = {}
    end

  end
end

And I'm using Devise for authentication..


Solution

  • I think you may have misunderstood the Rails relations and how to use them. As the methods to define relation are pretty much literal, take a good look at your models and 'read' them.

    • An item has one cart
    • A cart belongs to a item

    Does it make sense that an item has one cart? Wouldn't make more sense to a cart to have an item, or several?

    • A cart has one or more items
    • One item belongs to a cart

    And then, you just translate that into rails methods:

    class User < ActiveRecord::Base
      has_one :cart
    end
    
    class Cart < ActiveRecord::Base
      belongs_to :user #carts table must have a user_id field
      has_many :items
    end
    
    class Item < ActiveRecord::Base
      belongs_to :cart #items table must have a cart_id field
    end
    

    Now, let's return to the literals. So, if I have a user and want to know what items he has in a cart, what do I do?

    • I know a user has one cart
    • I know that a cart has one or more items

    So, to recover the items that a user has in a cart:

    user.cart.items
    

    And answering your original question, how to save the items to a user? You don't need to. If the user has a cart and this cart has items then, automatically, user has items (accessing them through the cart, as stated above).