delete has_many through relationship Ruby on Rails - ruby-on-rails

I'ved got a Ruby on Rails app
I have Block that has_many Unit that has_many User through user_unit_assocs.
The model is define as such.
class Block < ActiveRecord::Base
has_many :units, dependent: :destroy
class Unit < ActiveRecord::Base
belongs_to :block
has_many :users, :through => :user_unit_assocs, dependent: :destroy
has_many :user_unit_assocs, dependent: :destroy
class User < ActiveRecord::Base
has_many :units, :through => :user_unit_assocs
has_many :user_unit_assocs, dependent: :destroy
The problem is when I delete Block
- unit gets deleted
- user_unit_assoc gets deleted
- BUT the user of the unit DOES NOT GET DELETED
How do I solve this problem to make sure it cascade block to user as well. Problem is the through but I cant change now the table structure, how can I solve these dependent records deletion properly. Thanks.

Related

Dependent: :destroy only to the 2nd degree in has many through association

I have three models. A collection has many searches through items.
When a collection is destroyed, I'd like its items to be destroyed, but searches to be nullified, since they are still valid objects on their own.
Can this be done?
Here are my models:
class Collection < ApplicationRecord
has_many :searches, through: :items
has_many :items
has_many :searches, through: :suggestions
has_many :suggestions
end
class Item < ApplicationRecord
belongs_to :collection
belongs_to :search
end
class Search < ApplicationRecord
has_many :collections, through: :items
has_many :items
has_many :collections, through: :suggestions
has_many :suggestions
end
You can just delete the items, just add dependent: :destroy to has_many :items.
class Collection < ApplicationRecord
has_many :searches, through: :items
has_many :items, dependent: :destroy
end
After destroying a collection, the item is destroyed but the search will remain.
second solution
You could even apply dependent: :nullify to has_many :searches - getting the same result.
class Collection < ApplicationRecord
has_many :searches, through: :items, dependent: :nullify
has_many :items
end
From the docs:
collection.delete(object, …)
Removes one or more objects from the collection by setting their foreign keys to NULL. Objects will be in addition destroyed if they're associated with dependent: :destroy, and deleted if they're associated with dependent: :delete_all.
If the :through option is used, then the join records are deleted (rather than nullified) by default, but you can specify dependent: :destroy or dependent: :nullify to override this.

Can I use has_many through: without destroying all associated records on delete?

I'm trying to make a list of commissions to add to applicant_commissions.
ApplicantCommission.rb
belongs_to :applicant
belongs_to :commission
Applicant.rb
has_many :applicant_commissions
Commission.rb
has_many :applicant_commissions
The problem is, if I use has_many through: when I delete an Applicant, the Commission is removed too. (and visa versa)
Any suggestions how I can create and destroy this without losing the associated record?
You should have following relations in your file
ApplicantCommission.rb
belongs_to :applicant
belongs_to :commission
Applicant.rb
has_many :applicant_commissions, dependent: :destroy
has_many :commissions, through: :applicant_commissions
Commission.rb
has_many :applicant_commissions, dependent: :destroy
has_many :applications, through: :applicant_commissions
This way your assosiation will not be deleted.
Secondly i would recommend you to have a look at this 'mark_for_destruction' for deletion.
This will help you deleting things easily.
http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html

has_many through can not modify association

I have three models: Almon, Bela and Lingo
class Almon < ActiveRecord::Base
belongs_to :bela, dependent: :destroy
has_many :lingos, through: :bela, dependent: :delete_all
accepts_nested_attributes_for :bela
accepts_nested_attributes_for :lingos, :allow_destroy => true
end
I am trying to submit a nested form in Almon and I am getting
Cannot modify association 'Almon#Lingos' because the source reflection class 'Lingo' is associated to 'Bela' via :has_many.
Could anyone please tell me what I am doing wrong?
You need to use has_many instead of belongs_to as the following:
has_many :belaes, dependent: :destroy
has_many :lingoes, through: :belaes, dependent: :delete_all

Accessing associated objects through a specific table

I have the following:
class User < ActiveRecord::Base
has_many :saved_courses, dependent: :destroy
has_many :courses, through: :saved_courses
has_many :course_completions
has_many :courses, through: :course_completions
end
And its course counterpart:
class Course < ActiveRecord::Base
has_many :course_completions
has_many :users, through: :course_completions
has_many :saved_courses, dependent: :destroy
has_many :users, through: :saved_courses
end
Based on these relationships, how do I get an array of all of the courses that a #user has saved?
As in, when I do #user.courses, I want it grab its saved courses, but not completed courses. I tried to do #user.saved_courses.courses but that doesn't seem like a valid operation. And #user.saved_courses.to_a simply returns an array of saved_courses, whereas I need to go a step further from there and grab the courses that those saved_course items represent.
Bonus points: I'm trying to do this in the shortest, most elegant way possible. For example, I don't want to manually iterate over #user.saved_courses.to_a, find the courses and push them into an array.
Having two associations named the same thing isn't going to work. You're going to need to do something the effect of
class User < ActiveRecord::Base
has_many :saved_courses, dependent: :destroy
has_many :saved_course_courses, through: :saved_courses, source: :course
has_many :course_completions, dependent: :destroy
has_many :course_completion_courses, through: :course_completions, source: :course
end
Note the use of :source, which tells ActiveRecord which class the has_many is referring to. Then when you're going through and want all of a user's courses, you would do: user.saved_course_courses + user.course_completion_courses

Rails: Delete associated records on object destroy

I have 2 models
class Deal < ActiveRecord::Base
has_many :couponizations, dependent: :destroy
has_many :coupon_codes, through: :couponizations, source: :coupon_code, dependent: :destroy
accepts_nested_attributes_for :coupon_codes, allow_destroy: true
end
and
class CouponCode < ActiveRecord::Base
has_one :couponization, dependent: :destroy
has_one :deal, through: :couponization, source: :deal
which are linked by many-to-many relationship
class Couponization < ActiveRecord::Base
belongs_to :coupon_code
belongs_to :deal
end
Despite I specified dependent: :destroy option, when I delete deal, coupon codes are not being deleted. However couponizations are deleted successfully. Is there any way to delete associated nested records on object destroy?
The options dependent: :destroy is ignored when using with the :through (see doc). You have to do it manually, with a after_destroy callback for example.
class Deal
after_destroy :destroy_coupon_codes
private
def destroy_coupon_codes
self.coupon_codes.destroy_all
end
end
I recommend using :after_destroy callback, so if destroying some Deal instance fails for whatever reason you don't end up deleting all of its CouponCodes.
Here's an :after_destroy example that should work:
after_destroy { |record|
CouponCode.destroy(record.coupon_codes.pluck(:id))
}
Make sure to remove dependent: :destroy from has_many :couponizations in the Deals model, because all couponizations will now be destroyed by the has_one :couponization, dependent: :destroy in the CouponCode model.

Resources