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