Skip to content

Loading…

Add :with_deleted option to belongs_to #48

Closed
wants to merge 1 commit into from

5 participants

@donv

This option allows depending objects to access the dependent after it is soft-deleted. This was present in acts_as_paranoid and is useful for us.

Can you add this for the next release?

@TiagoCardoso1983

Hi,

This does not work when the association is polymorphic (or better said, the polymorphic association does not work if there is a with_deleted involved).

@donv

I'd be happy to work more on this. Do you perhaps have a test for the polymorphic case?

@TiagoCardoso1983

Hi, glad that you're on the subject. So, here it goes:

class SuperFreak < ActiveRecord::Base

belongs_to :loveable, :polymorphic => true, :with_deleted => true

end

So, the class of my loveable association will be defined on the loveable_class column. However, when i try to fetch it, it says the class "Loveable" does not exist (and rightfully so). This is mainly due to this snippet:

options[:class_name] || target.to_s.classify (line 213)

In the polymorphic case, neither is the class associated by class_name nor it should be created from the association target. I tried to correct this, but it seems I don't have a reference to the object whose association i'm trying to fetch. Maybe your ActiveRecord powers are mightier. Godspeed.

@TiagoCardoso1983

Hey man,

I think i came up with a relatively good workaround for the polymorphic thing. So, here is my input:


(#{options[:polymorphic].present?} ? send("#{target}_type").constantize : #{options[:class_name] || target.to_s.classify}).unscoped { #{target}_without_unscoped(*args) }

that is, of course, my replacement for that line i mentioned on the previous comment. If you have a different more elegant workaround, please let me know.

Cheers

@paulcc

Hi

A suggestion until (or instead of) this code gets added: add a brief note in the Readme of this repo explaining how to implement the effects of the old :with_deleted option in a particular model. This will save others some digging.

Paul

@goncalossilva

Pulled from #55. Thanks!

@tak2siva

Hi

I have duplicated :belongs_to code for :has_many relationship

but it looks like the code is not executed in with_deleted scope

Can anybody correct me

https://github.com/tak2siva/acts_as_paranoid/blob/master/lib/acts_as_paranoid/associations.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 20, 2011
  1. @donv
Showing with 36 additions and 1 deletion.
  1. +2 −0 .gitignore
  2. +18 −0 lib/rails3_acts_as_paranoid.rb
  3. +15 −1 test/rails3_acts_as_paranoid_test.rb
  4. +1 −0 test/test_helper.rb
View
2 .gitignore
@@ -1,2 +1,4 @@
+*~
pkg
.bundle
+.idea
View
18 lib/rails3_acts_as_paranoid.rb
@@ -201,3 +201,21 @@ def paranoid_value=(value)
# Push the recover callback onto the activerecord callback list
ActiveRecord::Callbacks::CALLBACKS.push(:before_recover, :after_recover)
+
+# This adds the :with_deleted option to belongs_to
+module ActiveRecord::Associations::ClassMethods
+ def belongs_to_with_deleted(target, options = {})
+ with_deleted = options.delete(:with_deleted)
+ result = belongs_to_without_deleted(target, options)
+ if with_deleted
+ class_eval <<-EOF
+ def #{target}_with_unscoped(*args)
+ #{options[:class_name] || target.to_s.classify}.unscoped { #{target}_without_unscoped(*args) }
+ end
+ alias_method_chain :#{target}, :unscoped
+ EOF
+ end
+ result
+ end
+ alias_method_chain :belongs_to, :deleted
+end
View
16 test/rails3_acts_as_paranoid_test.rb
@@ -4,7 +4,7 @@ class ParanoidBaseTest < ActiveSupport::TestCase
def assert_empty(collection)
assert(collection.respond_to?(:empty?) && collection.empty?)
end
-
+
def setup
setup_db
@@ -263,6 +263,20 @@ def test_removal_with_associations
assert_equal 0, ParanoidDeleteCompany.with_deleted.count
assert_equal 0, ParanoidProduct.with_deleted.count
end
+
+ def test_paranoid_belongs_to
+ paranoid_time_object = ParanoidTime.first
+ has_many_object = paranoid_time_object.paranoid_has_many_dependants.create(:name => "has_many")
+
+ assert has_many_object.paranoid_time
+ assert has_many_object.paranoid_time_with_deleted
+
+ paranoid_time_object.destroy
+
+ assert_nil has_many_object.paranoid_time(true)
+ assert has_many_object.paranoid_time_with_deleted(true)
+ end
+
end
class InheritanceTest < ParanoidBaseTest
View
1 test/test_helper.rb
@@ -162,6 +162,7 @@ class HasOneNotParanoid < ActiveRecord::Base
class ParanoidHasManyDependant < ActiveRecord::Base
acts_as_paranoid
belongs_to :paranoid_time
+ belongs_to :paranoid_time_with_deleted, :class_name => 'ParanoidTime', :foreign_key => :paranoid_time_id, :with_deleted => true
belongs_to :paranoid_belongs_dependant, :dependent => :destroy
end
Something went wrong with that request. Please try again.