Reputation: 127
Have a problem regarding saving ActiveRecord associations and need your help :)
I need to add articles merging functionality to legacy code.
It's expected to work the following way:
Here's my Article model code (reduced for readability).
class Article < Content
before_destroy :reload_associated_comments
has_many :comments, :dependent => :destroy, :order => "created_at ASC" do
def reload_associated_comments
unless self.comments.empty?
article = Article.find(@merge_with)
self.comments.each do |comment|
comment.article = article
article.save!
end
end
end
def merge_with(id)
@merge_with = id
article = Article.find(@merge_with)
if !article.nil?
text = article.body + body
article.body = text
article.save!
self.destroy
return article
end
nil
end
end
Here's Comment model (also reduced):
class Comment < Feedback
belongs_to :article
end
The problem is when I return from before_destroy hook nothing has been saved to the database. I check it via the following:
eval Article.find(target_article_id).comments
Save raises no exceptions. What I'm missing here?
Thanks in advance!
This worked for me
def merge_with(id)
@merge_with = id
article = Article.find(@merge_with)
unless article.nil?
text = article.body + body
article.body = text
article.save!
reload_associated_comments
self.reload
self.destroy
return article
end
nil
end
Upvotes: 0
Views: 676
Reputation: 18530
Actually Rails destroy every comment before calling the before_destroy
callback for the article. That's sadly how rails work. Changing this behavior would imply breaking legacy apps. You can find more information on this issue here: https://github.com/rails/rails/issues/670
In my opinion the best solution is to override the destroy
method and get rid of the callback:
class Article < Content
def destroy
reload_associated_comments
super
end
has_many :comments, :dependent => :destroy, :order => "created_at ASC" do
def reload_associated_comments
unless self.comments.empty?
article = Article.find(@merge_with)
self.comments.each do |comment|
comment.article = article
comment.save!
end
end
end
def merge_with(id)
@merge_with = id
article = Article.find(@merge_with)
if !article.nil?
text = article.body + body
article.body = text
article.save!
self.destroy
return article
end
nil
end
end
Also, as @Zippie mentioned, you should call comment.save!
instead of article.save!
Hope it helps!
Upvotes: 1