Home > front end >  Cannot destroy a model with a has_many through assocation
Cannot destroy a model with a has_many through assocation

Time:03-25

I have the following models linked through a has_many :through associaton. Below is the following models

class Campaign
  has_many :email_notification_code_percentages, dependent: :destroy
  has_many :email_notification_code_percentage_trackers, through: :email_notification_code_percentages
end

class EmailNotificationCodePercentage < ApplicationRecord
  belongs_to :campaign
  has_many :email_notification_code_percentage_trackers, dependent: :destroy
end

class EmailNotificationCodePercentageTracker < ApplicationRecord
  belongs_to :email_notification_code_percentage
end


When I try execute the following @campaign.email_notification_code_percentage_trackers.destroy_all I get the following error:

Cannot modify association 'Campaign#email_notification_code_percentage_trackers' because the source reflection class 'EmailNotificationCodePercentageTracker' is associated to 'EmailNotificationCodePercentage' via :has_many. (ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection)

What is the issue here? This should be a simple has many through association as defined through the rails examples. What am I missing here? This looks correct to me.

CodePudding user response:

This is the expected behavior, as you can read in the API docs (https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html):

An important caveat with going through has_one or has_many associations on the join model is that these associations are read-only.

Associations with the :through option or defined via the has_and_belongs_to_many macro are a bit special.

So, a couple of alternative ways:

  1. Iterate over each elem:
# be careful if the association is very large, you can run into some memory or timeout issues
@campaign.email_notification_code_percentage_trackers.each(&:destroy)
  1. Make the query a bit different to be able to use the destroy_all:
EmailNotificationCodePercentage.merge(@campaign.email_notification_code_percentage_trackers).destroy_all
  • Related