Reputation: 366
class Concert < ActiveRecord::Base
has_many :documents, :uniq => true
accepts_nested_attributes_for :documents #???, :allow_destroy => true
class Artist < ActiveRecord::Base
has_one :document, :validate => true
accepts_nested_attributes_for :document #???, :allow_destroy => true
class Document < ActiveRecord::Base
belongs_to :artist
belongs_to :concert
I want to remove a document from concerts: Destroy it, if its only parent is a concert, but set concert_id to nil and save document, if it also belongs_to an artist. (and analogue idea from artist point of view)
I would like to either:
.marked_for_destruction
? And stop destruction of document if it is referenced by the other parent. How do I do that?Or even better:
I have explored polymorphic associations, but I need the SAME document to belong_to 2 parents.
Have lost the plot if it makes any difference, but for completeness sake: Concert and Artist are in a has_many :through => :engagements association
Adding this in Concert (and analogue in Artist) as before_save callbacks works:
def documents_for_deletion?
self.documents.each do |doc|
if doc.marked_for_destruction?
unless doc.artist_id.blank?
doc.reload
doc.concert_id = nil
end
end
end
end
http://api.rubyonrails.org/classes/ActiveRecord/AutosaveAssociation.html
Is there a way to do it in Document as a before_destroy callback? (which I would prefer, see above)
Upvotes: 1
Views: 529
Reputation: 44715
You can use association callbacks, like after_remove:
class Concert < ActiveRecord::Base
has_many :documents, :uniq => true, :after_remove => :destroy_document_with_no_parent
def destroy_document_with_no_parent(removed_document)
removed_document.destroy unless removed_document.concert_id || removed_document.artist_id
end
You probably should place the method in some helper so you wouldn't need to repeat the code in two classes.
Upvotes: 1