On Saturday, July 29, 2006, at 1:29 PM, Daniel N wrote: >On 7/27/06, Jeremy Kemper <[EMAIL PROTECTED]> wrote: >> >> On Jul 26, 2006, at 6:06 AM, Daniel N wrote: >> > I've had a crack at this one and it is as I feared. >> > >> > If I define the restrict association first, then the destroy chain >> > is halted and all is well. But if I have an association where >> > a :dependent => :destroy is declared before the association >> > with :restrict then the first association is destroyed before the >> > destroy chain is halted. >> >> You can wrap the destroy method to leapfrog the callback chain. >> >> associations.rb, configure_dependency_* >> >> case reflection.options[:dependent] >> when :restrict >> class_eval <<-end_eval >> def destroy_with_has_many_#{reflection.name} >> unless #{reflection.name}.blank? >> raise DestroyRestricted.new(self, # >> {reflection.name.inspect}) >> end >> end >> >> alias_method_chain :destroy, "has_many_#{reflection.name}" >> end_eval >> # ... >> end >> >> >> base.rb >> >> module ActiveRecord >> class DestroyRestricted < ActiveRecordError >> def initialize(model, by) >> super "#{model.class.name} #{model.id} destroy restricted by >> #{by}" >> end >> end >> end >> >> >> > I have taken my first real plunge into the rails source and found a >> > number of places where I thought a transaction might go to prevent >> > this but to no avail. Actually my head is spinning a bit trying to >> > put all the pieces of active_record together. >> > >> > For this to work I think I need to put a transaction around the >> > entire destroy chain, but I have no idea how to do this. >> > >> > Any pointers anyone could give would be great. >> >> destroy and its callbacks are wrapped in a single transaction (see >> transactions.rb) so you can raise an exception to rollback. >> >> >> example: >> >> class ParentController < ApplicationController >> def destroy >> @parent.destroy >> redirect_to parent_url(@parent) >> rescue ActiveRecord::DestroyRestricted => restricted >> flash[:error] = restricted.message >> redirect_to :back >> end >> end >> >> >> Best, >> jeremy >> _______________________________________________ >> Rails-core mailing list >> Rails-core@lists.rubyonrails.org >> http://lists.rubyonrails.org/mailman/listinfo/rails-core >> > >Thanx Jeremy. This looks very different to what I had in mind. Lots >better :) > >I'll get into trying to get this to work. > >Just a thought tho. By raising an exception, this would put destroy into a >different category, this should perhaps be destroy! to fit with the other >methods that raise errors. > >Would including an exception into the destory method mean that it would >break exisitng code? I guess you would only need to use a rescue if you >have declared a relationship as rectricted. I'll have a go anyway and see >what ppl think. > >Thanx for you help > >Cheers > > >_______________________________________________ >Rails-core mailing list >Rails-core@lists.rubyonrails.org >http://lists.rubyonrails.org/mailman/listinfo/rails-core >
Wouldn't it make sense to have it call a function like 'can_destroy?' before trying to do the work? Have that function recursively call itself on all the child objects, and then only return true if all dependent objects can be destroyed. If can_destroy? returns false, then... don't destroy it. It might be a little more robust than relying on exceptions, since it will test everything before trying to destroy anything. _Kevin www.sciwerks.com -- Posted with http://DevLists.com. Sign up and save your mailbox. _______________________________________________ Rails-core mailing list Rails-core@lists.rubyonrails.org http://lists.rubyonrails.org/mailman/listinfo/rails-core