nothing-special-here
nothing-special-here

Reputation: 12568

How to destroy Rails model without calling dependent: :destroy on associations

Is there a a way to destroy Rails model without calling callbacks for dependent: :destroy in associations.

example:

class Administration < ActiveRecord::Base
  include IdentityCache

  attr_accessible :auto_sync, :response_rate_calc_state, :description,
    :year, :project_id, :season, :auto_async, :synchronized_at

  has_many :report_distributions 
  has_many :rosters, dependent: :destroy

  before_destroy :delete_file

  attr_accessible :file

  has_attached_file :file,
      path: ":class/:id_partition/:basename.:extension",
      storage: :s3,
      bucket: S3Config::AWS_BUCKET_MODELS,
      s3_credentials: {
          access_key_id: S3Config::AWS_ACCESS_KEY_ID_MODELS,
          secret_access_key: S3Config::AWS_SECRET_ACCESS_KEY_MODELS
      },
      s3_permissions: 'authenticated-read',
      s3_protocol: 'https',
      s3_storage_class: :reduced_redundancy

  def authenticated_url(style = nil, expires_in = 10.seconds)
    file.s3_object(style).url_for(:read, secure: true, expires: expires_in).to_s
  end

  def delete_file
    file.s3_object(nil).delete if self.file?
  end

# ...

So when I call

Administration.find(id).destroy

I want to just delete record and attachment file, but DO NOT call callbacks for deleting rosters

has_many :rosters, dependent: :destroy

--

PS I don't want to disable has_many :rosters, dependent: :destroy. I just need to temporary disable callback.

Upvotes: 13

Views: 12812

Answers (1)

Nimir
Nimir

Reputation: 5839

You can keep your association as it is and skip the callback one of the following ways:

1. Using delete instead of destroy since it won't fire callbacks

Administration.find(id).delete

2. Use skip_callback method (found it in this blog post):

 Administration.skip_callback(:destroy, :bofore, :action_you_need_to_disable)
 #then safely destroy without firing the action_you_need_to_disable callback
 Administration.find(id).destroy

3. Or even better, if you already know when you need to skip the callback, you could do:

class Admistration < ActiveRecord::Base
  has_many :rosters, dependent: :destroy
  skip_callback :destroy, :before, :action_you_need_to_disable, if: -> { #conditions }
end

Link: api docs on skip_callback

Upvotes: 22

Related Questions