Sambhav Sharma
Sambhav Sharma

Reputation: 5860

Rails 5 dependent: :destroy doesn't work

I have the following classes:

class Product < ApplicationRecord
  belongs_to :product_category

  def destroy
    puts "Product Destroy!"
  end

end

class ProductCategory < ApplicationRecord
  has_many :products, dependent: :destroy

  def destroy
    puts "Category Destroy!"
  end
end

Here, I am trying to override the destroy method where I eventually want to do this:

update_attribute(:deleted_at, Time.now)

When I run the following statement in Rails console: ProductCategory.destroy_all I get the following output

Category Destroy!
Category Destroy!
Category Destroy!

Note: I have three categories and each category has more than one Products. I can confirm it by ProductCategory.find(1).products, which returns an array of products. I have heard the implementation is changed in Rails 5. Any points on how I can get this to work?

EDIT

What I eventually want is, to soft delete a category and all associated products in one go. Is this possible? Or will ave to iterate on every Product object in a before destroy callback? (Last option for me)

Upvotes: 1

Views: 1489

Answers (2)

Sambhav Sharma
Sambhav Sharma

Reputation: 5860

So this is how I did it in the end:

class Product < ApplicationRecord
  belongs_to :product_category

  def destroy
    run_callbacks :destroy do
      update_attribute(:deleted_at, Time.now)
      # return true to escape exception being raised for rollback
      true
    end
  end

end

class ProductCategory < ApplicationRecord
  has_many :products, dependent: :destroy

  def destroy
    # run all callback around the destory method
    run_callbacks :destroy do
      update_attribute(:deleted_at, Time.now)
      # return true to escape exception being raised for rollback
      true
    end
  end
end

I am returning true from the destroy does make update_attribute a little dangerous but I am catching exceptions at the ApplicationController level as well, so works well for us.

Upvotes: 1

Jovica Šuša
Jovica Šuša

Reputation: 622

You should call super from your destroy method:

def destroy
  super 
  puts "Category destroy"
end

But I definitely wouldn't suggest that you overide active model methods.

Upvotes: 1

Related Questions