-
Notifications
You must be signed in to change notification settings - Fork 901
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restore has_many through association when undoing a destroy #121
Comments
Thank you for posting your code. It's a good solution to the perennial problem of restoring associations. Please could you explain this line? ver.reify.save! if ver.event == 'destroy' && ver.created_at > 20.seconds.ago Will it only restore the team's members if you try to restore the team within 20 seconds of destroying it? Wouldn't you just want the last destroy event? |
Since I was only looking to restore items when a user clicks undo on removing an item, I used 20.seconds.ago I wasn't sure how to get the last destroy for the children, because when the parent is recreated, it does not yet have children again. One case: Second case: So I changed the restore method to be: def restore_children
if children && recreating_item?
children.each do |model_name|
records = Version.where(:item_type => model_name.classify, :event => 'destroy')
records.each do |ver|
ver.reify.save! if ver.created_at > item.versions[-2].created_at - 1.seconds # checking the time for the destroy version
#temp_object = ver.reify if ver.created_at > item.versions[-2].created_at - 1.seconds
#temp_object.save! if temp_object.send(item.class.name.tableize.singularize).id == item.id
end
end
end
end The commented out lines are something else I tried, to check that the child's parent is the item being restored. The restore children method is still not ideal. I can think of ways it can break. For example if removing multiple teams within 1 second range, which happens in my test. So in the test, I delay the second remove by a few seconds. |
Hmm, how about changing your Team class to store the team members' ids. Then the Version class can look at each team member's versions for a destroy event which occurred at the same time as the team was destroyed. I.e.: class Team < ActiveRecord::Base
has_paper_trail :meta => { :children => Proc.new { |team| ['team_members' => team.team_members.map(&:id)] } }
has_many :team_members, :dependent => :destroy
end
class Version < ActiveRecord::Base
attr_accessible :children
serialize :children, Array
after_save :restore_children
def recreating_item?
if item
item.versions[-1].try(:event) == 'create' && item.versions[-2].try(:event) == 'destroy'
end
end
def restore_children
if children && recreating_item?
children.each do |model_name, model_ids|
model_ids.each do |model_id|
child_versions = Version.where(:item_type => model_name.classify,
:item_id => model_id,
:event => 'destroy')
child_versions.each do |ver|
ver.reify.save! if (ver.created_at - item.versions[-2].created_at).abs < 1.seconds
end
end
end
end
end
end |
I tried that approach before. My problem was that if I create children models using team_member_ids which does not fire a new version for the parent model. |
@elle did you ever solve this using paper_trail or any other gem? I am currently struggling with various hacks around the problem but would like to come up with something more general that could be committed back. Honestly though I don't care so much about destroyed children as I do about continuously updated children. |
Closed via PR #439, which was just merged! |
This is based on Ryan Bates' railcast and I am only trying to restore deleted join records.
I am manually defining which children I would like to restore as a meta column on versions, like so:
I could be checking if the child model responds_to? :versions but since I manually define which models I would like to go through, I didn't think it was necessary.
One problem is that I am only looking 20.seconds.ago for recent records. But that option will only occur when people click on the 'undo destroy' link.
Anyhow, this works for me.
The text was updated successfully, but these errors were encountered: