-1

My relationship is as follows:

  • Users have many Cartitems; Cartitems belong to Users,
  • Cartitems have many Products; Products belong to Cartitems
  • Therefore, Users have many Products through Cartitems and Cartitems have many Users through products.

I am trying to individually route to each users cartitems, something along the liens of: /users/:user_id/cartitems which will route to an array of cartitems belonging to that user, where I can then post, patch and delete cartitems for each user.

The problem is the path '/users/1/cartitems' returns the same cartitems as '/users/2/cartitems', and when I post to '/users/2/cartitems', the products get posted to '/users/1/cartitems'. I'm not quite sure if this is a problem in my routes or in my models/controller.

Here are my models for Users and Cartitems:

class User < ApplicationRecord
  has_many :cartitems
  has_many :products, through: :cartitems
end


class Cartitem < ApplicationRecord
  belongs_to :user
  belongs_to :product
end

And here are my serializers for good measure:

class UserSerializer < ActiveModel::Serializer
  attributes :id, :username, :email
  has_many :cartitems
end


class CartitemsSerializer < ActiveModel::Serializer
  attributes :id, :user_id, :product_id, :quantity, :name, :price, :photo
end

And here is my Cartitems controller:

class Api::V1::CartitemsController < ApplicationController
  before_action :find_cartitem, only: [:update, :destroy]

  def index
    @cartitems = Cartitem.all
    render json: @cartitems
  end

  def create
    @cartitem = Cartitem.new(cartitem_params)
    if @cartitem.valid?
      @cartitem.save
      render json: @cartitem, status: :accepted
    else
      render json: {errors: @cartitem.errors.full_messages}, status: :unprocessible_entity
    end
  end

  def update
    @cartitem.update(cartitem_params)
    if @cartitem.save
      render json: @cartitem, status: :accepted
    else
      render json: {errors: @cartitem.errors.full_messages}, status: :unprocessible_entity
    end
  end

  def destroy
    @cartitem.destroy
    render json: @cartitem, status: :accepted
  end

end

private

def cartitem_params
  params.require(:cartitem).permit(:user_id, :product_id, :quantity, :name, :price, :photo)
end

def find_cartitem
  @cartitem = Cartitem.find(params[:id])
end

I want to be able to post to '/users/:user_id/cartitems' where each cartitems would be separate for each user ID. Any help would be greatly appreciated.

deejay123
  • 89
  • 7
  • Your code just does what you ask it to do : get all cartitems. Nowhere in your code you are using the param : `params[:user_id]` Maybe in your code, you can add a `before_action` where you get the requested user: `@user=User.find(params[:user_id])` and retrieve this very user cartitems in the index action. `@cartitems=@user.cartitems` (and adapt your code for each action as well) – Maxence Sep 16 '19 at 23:54
  • @Maxence hey thanks for the reply. Do you think you can elaborate a little further? I'm quite new to rails. – deejay123 Sep 17 '19 at 01:38
  • @Emu has summed up my comment :) his answer has the index action coded. Let us know if you have trouve for other action. – Maxence Sep 17 '19 at 09:24

1 Answers1

0

In your index you're not collecting user specific cartitems. Whenever a call made to this index action using: /users/:user_id/cartitems, you need to fetch the user first, then show cart items belongs to that user.

Here is a solution:

def index
    @cartitems = User.find(params[:user_id]).cart_items
    render json: @cartitems
end

Better to create a before_action callback for every action inside this CartitemsController because you defined a nested route. Like:

before_action :find_cartitem, only: [:update, :destroy]
before_action :find_user

def index
    @cartitems = @user.cart_items
    render json: @cartitems
end

private
def find_cartitem
  @cartitem = Cartitem.find(params[:id])
end

def find_user
  @user = User.find(params[:user_id])
end
Emu
  • 5,763
  • 3
  • 31
  • 51