From d4f21c75e65ecef6c08034c22e5c0a6451a9a030 Mon Sep 17 00:00:00 2001 From: Hongli Lai (Phusion) Date: Sun, 21 Sep 2008 23:51:02 +0200 Subject: [PATCH] Add an 'extra_conditions' parameter to configure_dependency_for_has_many for supporting certain plugins, and make the generated callbacks open a transaction. --- activerecord/lib/active_record/associations.rb | 31 +++++++++++++++++++++-- 1 files changed, 28 insertions(+), 3 deletions(-) diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 3cad914..6442803 100755 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1428,17 +1428,28 @@ module ActiveRecord [] end + # Creates before_destroy callback methods that nullify, delete or destroy + # has_many associated objects, according to the defined :dependent rule. + # # See HasManyAssociation#delete_records. Dependent associations # delete children, otherwise foreign key is set to NULL. - def configure_dependency_for_has_many(reflection) + # + # The +extra_conditions+ parameter, which is not used within the main + # Active Record codebase, is meant to allow plugins to define extra + # finder conditions. + def configure_dependency_for_has_many(reflection, extra_conditions = nil) if reflection.options.include?(:dependent) # Add polymorphic type if the :as option is present dependent_conditions = [] dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}" dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as] dependent_conditions << sanitize_sql(reflection.options[:conditions]) if reflection.options[:conditions] + dependent_conditions << extra_conditions if extra_conditions dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ") + # Note: the use of transactions in the generated callback methods + # are intentional: it allows plugins to hook into the behavior. + case reflection.options[:dependent] when :destroy method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym @@ -1447,9 +1458,23 @@ module ActiveRecord end before_destroy method_name when :delete_all - module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" + module_eval %Q{ + before_destroy do |record| + record.#{reflection.name}.transaction do + #{reflection.class_name}.delete_all("#{dependent_conditions}") + end + end + } when :nullify - module_eval "before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL), %(#{dependent_conditions})) }" + module_eval %Q{ + before_destroy do |record| + record.#{reflection.name}.transaction do + #{reflection.class_name}.update_all( + "#{reflection.primary_key_name} = NULL", + "#{dependent_conditions}") + end + end + } else raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, or :nullify (#{reflection.options[:dependent].inspect})" end -- 1.6.0.2