The test should update the item (which is already created) with the tag_id that was placed into the tag_id parameter. I know that I can do this because I have tried it on postman and it works every time. Rspec tells me that the tags is invalid even though I logged its id (which means that it exists).
Any help would be appreciated.
rspec code error message with logs
I tried to change the way of input; I've placed "tag.id" into the array expecting it to read it as an integer and I have tried every other way of inputting the number into the array.
I also know that the problem is with the array because once I leave it empty (aka: []) it works perfectly fine.
Note: I am 100% sure that the code works because it works on postman.
Code in items_controller.rb for updating an item:
def update
item = Item.find(params[:id])
item.item_tags.destroy_all
error_exist = false
params[:tag_id].each do |tag_id|
if ItemTag.find_by(tag_id: tag_id) == nil
error_exist = true
break
else
item.tags << Tag.find(tag_id)
end
end
@items = item
if error_exist == false
if current_user.id == item.user_id
if item.update(item_params)
if item.is_sold == true
if item.bids.last != nil
item.bids.last.update_attribute(:is_accepted, true)
end
else
if item.bids.last != nil
item.bids.last.update_attribute(:is_accepted, false)
end
end
render 'items/update'
else
render json: {status: "Error", message: "Item not updated", data:item.errors}, status: :unprocessable_entity
end
else
render json: {status: "Error", message: "Item is not yours"}, status: :unauthorized
end
else
render json: {status: "Error", message: "Invalid tags"}, status: :unprocessable_entity
end
end
private
def item_params
params.permit(:name, :price, :is_auction, :is_sold)
end
Note 2: Passing in nothing, a single tag_id, or multiple tags should work. The only time it would render invalid tags is if one of the tag_is does not exist.
CodePudding user response:
The problem is here.
params[:tag_id].each do |tag_id|
if ItemTag.find_by(tag_id: tag_id) == nil
error_exist = true
break
else
item.tags << Tag.find(tag_id)
end
end
Your test passes Tag.last.id
as tag_id
but your code is searching by ItemTag.find_by(tag_id: tag_id)
. The conclusion is that the tag is missing from ItemTag
.
Digging deeper, you're not asking "does this tag exist", but "does any item already use this tag" which seems odd.
You're also deleting all the tags from the item in question, which will impact the tag not being in ItemTag...
item = Item.find(params[:id])
item.item_tags.destroy_all
...and then pushing the new tags on one by one. I think the intent is to make sure you fully replace the item's tags, but this is done with item.tags = tags
.
A better approach is to replace the tags in one go.
# Check if the item exists.
item = Item.find(params[:id])
if !item
# Not found is the appropriate response. See
# https://restfulapi.net/http-status-codes/
render json: {status: "Error", message: "Item #{params[:id]} was not found"}, status: :not_found
return
end
# Get the tags, make sure they exist.
begin
tags = Tag.find(params[:tag_Id])
rescue ActiveRecord::RecordNotFound => e
# Not found is the appropriate response. See
# https://restfulapi.net/http-status-codes/
render json: {status: "Error", message: "Tag #{e.primary_key} was not found"}, status: :not_found
return
end
# Delete and add tags as necessary.
item.tags = tags