diff options
Diffstat (limited to 'activerecord/lib')
6 files changed, 48 insertions, 7 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 58725246c8..b44ab26a73 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1097,8 +1097,7 @@ module ActiveRecord # 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> this object raises an <tt>ActiveRecord::DeleteRestrictionError</tt> exception and - # cannot be deleted if it has any associated objects. + # <tt>:restrict</tt> this object cannot be deleted if it has 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 @@ -1251,8 +1250,7 @@ module ActiveRecord # 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+. - # Also, association is assigned. If set to <tt>:restrict</tt> this object raises an - # <tt>ActiveRecord::DeleteRestrictionError</tt> exception and cannot be deleted if it has any associated object. + # If set to <tt>:restrict</tt>, this object cannot be deleted if it has any associated object. # [: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 6e2e5f9de0..54e51b7f44 100644 --- a/activerecord/lib/active_record/associations/builder/association.rb +++ b/activerecord/lib/active_record/associations/builder/association.rb @@ -51,5 +51,19 @@ module ActiveRecord::Associations::Builder association(name).writer(value) end end - end + + def dependent_restrict_raises? + ActiveRecord::Base.dependent_restrict_raises == true + 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 + end + 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 fc6799fb15..0fe32b5f16 100644 --- a/activerecord/lib/active_record/associations/builder/has_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_many.rb @@ -21,6 +21,7 @@ module ActiveRecord::Associations::Builder ":nullify or :restrict (#{options[:dependent].inspect})" end + dependent_restrict_deprecation_warning if options[:dependent] == :restrict send("define_#{options[:dependent]}_dependency_method") model.before_destroy dependency_method_name end @@ -55,7 +56,15 @@ module ActiveRecord::Associations::Builder def define_restrict_dependency_method name = self.name mixin.redefine_method(dependency_method_name) do - raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).empty? + if send(name).exists? + if dependent_restrict_raises? + raise ActiveRecord::DeleteRestrictionError.new(name) + else + errors.add(:base, I18n.t("activerecord.errors.messages.restrict_dependent_destroy", + :model => name)) + return false + end + end end end diff --git a/activerecord/lib/active_record/associations/builder/has_one.rb b/activerecord/lib/active_record/associations/builder/has_one.rb index 7a6cd3890f..d9fed4b7f2 100644 --- a/activerecord/lib/active_record/associations/builder/has_one.rb +++ b/activerecord/lib/active_record/associations/builder/has_one.rb @@ -34,6 +34,7 @@ module ActiveRecord::Associations::Builder ":nullify or :restrict (#{options[:dependent].inspect})" end + dependent_restrict_deprecation_warning if options[:dependent] == :restrict send("define_#{options[:dependent]}_dependency_method") model.before_destroy dependency_method_name end @@ -55,7 +56,15 @@ module ActiveRecord::Associations::Builder def define_restrict_dependency_method name = self.name mixin.redefine_method(dependency_method_name) do - raise ActiveRecord::DeleteRestrictionError.new(name) unless send(name).nil? + unless send(name).nil? + if dependent_restrict_raises? + raise ActiveRecord::DeleteRestrictionError.new(name) + else + errors.add(:base, I18n.t("activerecord.errors.messages.restrict_dependent_destroy", + :model => name)) + return false + end + end end end end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index a774af6024..a2ce620354 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -72,6 +72,16 @@ module ActiveRecord # The connection handler config_attribute :connection_handler self.connection_handler = ConnectionAdapters::ConnectionHandler.new + + ## + # :singleton-method: + # Specifies wether 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, :global => true + self.dependent_restrict_raises = true end module ClassMethods diff --git a/activerecord/lib/active_record/locale/en.yml b/activerecord/lib/active_record/locale/en.yml index 44328f63b6..88edabfd41 100644 --- a/activerecord/lib/active_record/locale/en.yml +++ b/activerecord/lib/active_record/locale/en.yml @@ -10,6 +10,7 @@ en: messages: taken: "has already been taken" record_invalid: "Validation failed: %{errors}" + restrict_dependent_destroy: "Cannot delete record because dependent %{model} exist" # Append your own errors here or at the model/attributes scope. # You can define own errors for models or model attributes. |