diff options
author | Jon Leighton <j@jonathanleighton.com> | 2012-08-10 12:33:51 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2012-08-10 17:45:06 +0100 |
commit | 5ad79989ef0a015fd22cfed90b2e8a56881e6c36 (patch) | |
tree | 8840456df7fb008c3306dae389f7cd73ec531977 /activerecord/lib | |
parent | d1835db6b5efce31af935aa804c7b537e14764d2 (diff) | |
download | rails-5ad79989ef0a015fd22cfed90b2e8a56881e6c36.tar.gz rails-5ad79989ef0a015fd22cfed90b2e8a56881e6c36.tar.bz2 rails-5ad79989ef0a015fd22cfed90b2e8a56881e6c36.zip |
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.
Diffstat (limited to 'activerecord/lib')
5 files changed, 38 insertions, 43 deletions
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 <tt>:destroy</tt> all the associated objects are destroyed - # alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated - # objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated - # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to - # <tt>:restrict</tt> 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: + # + # * <tt>:destroy</tt> causes all the associated objects to also be destroyed + # * <tt>:delete_all</tt> causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute) + # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Callbacks are not executed. + # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records + # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects # # If using with the <tt>:through</tt> 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 <tt>has_one :manager</tt> 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 <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to - # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. - # If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+. - # If set to <tt>:restrict</tt>, 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: + # + # * <tt>:destroy</tt> causes all the associated objects to also be destroyed + # * <tt>:delete</tt> causes all the asssociated objects to be deleted directly from the database (so callbacks will not execute) + # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Callbacks are not executed. + # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records + # * <tt>:restrict_with_error</tt> 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 |