Slowboy Slowboy - 2 months ago 8
Ruby Question

PG::ForeignKeyViolation When deleting categories/labels in Active Admin

I'm using

Active Admin
so the
adminuser
can create/delete categories, labels and products.

I can create
Labels
,
Categories
and
Products
with out any problems but when I want to delete Labels or Categories I always get this error:

PG::ForeignKeyViolation at /admin/labels/2


ERROR: update or delete on table "labels" violates foreign key constraint "fk_rails_5a55c39b94" on table "products"
DETAIL: Key (id)=(2) is still referenced from table "products".


And if I try to destroy product I get this flash message
Product could not be destroyed.


It seems to me that I'm getting this error when I delete
labels
or
categories
that are assigned to product.

I'm not sure what to do to fix it

Below is the relevant code

app/admin/product.rb


ActiveAdmin.register Product do

permit_params :title, :description, :image, :price_usd, :price_isl, :category_id, :label_id

index do
column :title
column :category
column :label
column :created_at

column :price_isk, :sortable => :price_isl do |product|
number_to_currency(product.price_isl, :unit => "ISK " , :precision => 0)
end
column :price_euro, :sortable => :price_usd do |product|
number_to_currency(product.price_usd, :unit => "€ " , :precision => 0)
end

actions
end
end


app/admin/label.rb


ActiveAdmin.register Label do
permit_params :name
end


app/admin/category.rb


ActiveAdmin.register Category do
permit_params :name
end


And in the
app/models/product.rb


class Product < ActiveRecord::Base
belongs_to :category
belongs_to :label

has_many :product_item

before_destroy :ensure_not_product_item

validates :title, :description, presence: true
validates :price_usd, :price_isl, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true

has_attached_file :image, styles: { medium: "500x500#", thumb: "100x100#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/

def ensure_not_product_item
if product_item.empty?
return true
else
errors.add(:base, 'You have Product Items')
return false
end

end
end


and the
app/models/label.rb


class Label < ActiveRecord::Base
has_many :products
has_many :pages
end


and the
app/models/category.rb


class Category < ActiveRecord::Base
has_many :products
end


and the
app/models/product_items.rb


class ProductItem < ActiveRecord::Base
belongs_to :product
belongs_to :cart
belongs_to :order


def total_price_usd
product.price_usd * quantity
end

def total_price_isl
product.price_isl * quantity
end

end

Answer

You could set the label_id or category_id in the product table to nil when you delete the category. Off the top of my head, but maybe something like:

Category Model:

before_destroy :remove_category_from_products

private

def remove_category_from_products
  Product.where(category_id: id).update_all(category_id: nil)  
end 

I mean, I don't have much context on the business logic in your app, but this should make it so you don't see that error anymore...

Comments