From 5ad79989ef0a015fd22cfed90b2e8a56881e6c36 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Fri, 10 Aug 2012 12:33:51 +0100 Subject: Remove the dependent_restrict_raises option. It's not really a good idea to have this as a global config option. We should allow people to specify the behaviour per association. There will now be two new values: * :dependent => :restrict_with_exception implements the current behaviour of :restrict. :restrict itself is deprecated in favour of :restrict_with_exception. * :dependent => :restrict_with_error implements the new behaviour - it adds an error to the owner if there are dependent records present See #4727 for the original discussion of this. --- activerecord/lib/active_record/associations.rb | 27 ++++++++------- .../associations/builder/association.rb | 38 +++++++++++----------- .../active_record/associations/builder/has_many.rb | 4 +-- .../active_record/associations/builder/has_one.rb | 3 +- activerecord/lib/active_record/core.rb | 9 ----- 5 files changed, 38 insertions(+), 43 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index f5ee4f3ebe..d9857b8fbd 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1094,12 +1094,14 @@ module ActiveRecord # [:primary_key] # Specify the method that returns the primary key used for the association. By default this is +id+. # [:dependent] - # If set to :destroy all the associated objects are destroyed - # alongside this object by calling their +destroy+ method. If set to :delete_all all associated - # objects are deleted *without* calling their +destroy+ method. If set to :nullify all associated - # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to - # :restrict an error will be added to the object, preventing its deletion, if any associated - # objects are present. + # Controls what happens to the associated objects when + # their owner is destroyed: + # + # * :destroy causes all the associated objects to also be destroyed + # * :delete_all causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute) + # * :nullify causes the foreign keys to be set to +NULL+. Callbacks are not executed. + # * :restrict_with_exception causes an exception to be raised if there are any associated records + # * :restrict_with_error causes an error to be added to the owner if there are any associated objects # # If using with the :through option, the association on the join model must be # a +belongs_to+, and the records which get deleted are the join records, rather than @@ -1203,11 +1205,14 @@ module ActiveRecord # from the association name. So has_one :manager will by default be linked to the Manager class, but # if the real class name is Person, you'll have to specify it with this option. # [:dependent] - # If set to :destroy, the associated object is destroyed when this object is. If set to - # :delete, the associated object is deleted *without* calling its destroy method. - # If set to :nullify, the associated object's foreign key is set to +NULL+. - # If set to :restrict, an error will be added to the object, preventing its deletion, if an - # associated object is present. + # Controls what happens to the associated objects when + # their owner is destroyed: + # + # * :destroy causes all the associated objects to also be destroyed + # * :delete causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute) + # * :nullify causes the foreign keys to be set to +NULL+. Callbacks are not executed. + # * :restrict_with_exception causes an exception to be raised if there are any associated records + # * :restrict_with_error causes an error to be added to the owner if there are any associated objects # [:foreign_key] # Specify the foreign key used for the association. By default this is guessed to be the name # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association diff --git a/activerecord/lib/active_record/associations/builder/association.rb b/activerecord/lib/active_record/associations/builder/association.rb index c3f32b5ed9..47f06421ee 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -85,35 +85,35 @@ module ActiveRecord::Associations::Builder raise ArgumentError, "The :dependent option expects either " \ "#{valid_options_message} (#{dependent.inspect})" end - end - def dependent_restrict_raises? - ActiveRecord::Base.dependent_restrict_raises == true + if dependent == :restrict + ActiveSupport::Deprecation.warn( + "The :restrict option is deprecated. Please use :restrict_with_exception instead, which " \ + "provides the same functionality." + ) + end end - def dependent_restrict_deprecation_warning - if dependent_restrict_raises? - msg = "In the next release, `:dependent => :restrict` will not raise a `DeleteRestrictionError`. "\ - "Instead, it will add an error on the model. To fix this warning, make sure your code " \ - "isn't relying on a `DeleteRestrictionError` and then add " \ - "`config.active_record.dependent_restrict_raises = false` to your application config." - ActiveSupport::Deprecation.warn msg + def define_restrict_with_exception_dependency_method + name = self.name + mixin.redefine_method(dependency_method_name) do + has_one_macro = association(name).reflection.macro == :has_one + if has_one_macro ? !send(name).nil? : send(name).exists? + raise ActiveRecord::DeleteRestrictionError.new(name) + end end end + alias define_restrict_dependency_method define_restrict_with_exception_dependency_method - def define_restrict_dependency_method + def define_restrict_with_error_dependency_method name = self.name mixin.redefine_method(dependency_method_name) do has_one_macro = association(name).reflection.macro == :has_one if has_one_macro ? !send(name).nil? : send(name).exists? - if dependent_restrict_raises? - raise ActiveRecord::DeleteRestrictionError.new(name) - else - key = has_one_macro ? "one" : "many" - errors.add(:base, :"restrict_dependent_destroy.#{key}", - :record => self.class.human_attribute_name(name).downcase) - return false - end + key = has_one_macro ? "one" : "many" + errors.add(:base, :"restrict_dependent_destroy.#{key}", + :record => self.class.human_attribute_name(name).downcase) + false end end end diff --git a/activerecord/lib/active_record/associations/builder/has_many.rb b/activerecord/lib/active_record/associations/builder/has_many.rb index 9e60dbc30b..63278c8cfd 100644 --- a/activerecord/lib/active_record/associations/builder/has_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_many.rb @@ -19,8 +19,8 @@ module ActiveRecord::Associations::Builder def configure_dependency if dependent = options[:dependent] - check_valid_dependent! dependent, [:destroy, :delete_all, :nullify, :restrict] - dependent_restrict_deprecation_warning if dependent == :restrict + check_valid_dependent! dependent, [:destroy, :delete_all, :nullify, :restrict, + :restrict_with_error, :restrict_with_exception] send("define_#{dependent}_dependency_method") model.before_destroy dependency_method_name diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb index 9c84f1913a..82c5905caf 100644 --- a/activerecord/lib/active_record/associations/builder/has_one.rb +++ b/activerecord/lib/active_record/associations/builder/has_one.rb @@ -25,8 +25,7 @@ module ActiveRecord::Associations::Builder def configure_dependency if dependent = options[:dependent] - check_valid_dependent! dependent, [:destroy, :delete, :nullify, :restrict] - dependent_restrict_deprecation_warning if dependent == :restrict + check_valid_dependent! dependent, [:destroy, :delete, :nullify, :restrict, :restrict_with_error, :restrict_with_exception] send("define_#{dependent}_dependency_method") model.before_destroy dependency_method_name diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 1145d2138c..0fddfdf0cb 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -82,15 +82,6 @@ module ActiveRecord # The connection handler config_attribute :connection_handler - ## - # :singleton-method: - # Specifies whether or not has_many or has_one association option - # :dependent => :restrict raises an exception. If set to true, the - # ActiveRecord::DeleteRestrictionError exception will be raised - # along with a DEPRECATION WARNING. If set to false, an error would - # be added to the model instead. - config_attribute :dependent_restrict_raises - %w(logger configurations default_timezone schema_format timestamped_migrations).each do |name| config_attribute name, global: true end -- cgit v1.2.3