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

Reply via email to