acts_as_paranoid 0.4.1 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/LICENSE +1 -1
 - data/{README.markdown → README.md} +26 -17
 - data/lib/acts_as_paranoid/core.rb +16 -8
 - data/lib/acts_as_paranoid/relation.rb +2 -2
 - data/lib/acts_as_paranoid/version.rb +3 -0
 - data/lib/acts_as_paranoid.rb +10 -14
 - data/test/test_associations.rb +222 -0
 - data/test/test_core.rb +387 -0
 - data/test/test_default_scopes.rb +52 -0
 - data/test/test_helper.rb +442 -0
 - data/test/test_inheritance.rb +14 -0
 - data/test/test_observers.rb +16 -0
 - data/test/test_relations.rb +117 -0
 - data/test/test_validations.rb +42 -0
 - metadata +102 -28
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA1:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 57c69c6d7676bda21b0f8da016bd556f77003894
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 5293e8a3b417fecdfe117aefddcd8e2a0d2f4b09
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 8ae49e59c2f487c80243bb42c4d6e33c4f1676ecd0d039ba420c1e1e49e02b83a4c6635515d1ef53dd4ba0c68ebce427b386ce684992d4139ef2e4c638f61dd5
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: f449a10feae541515688ed6c55446aa815025982f293a2375c44ec74b68a8cfe7928abc1dffee3758a868bca4d6d92eb13632642bb0dc40279d47e5973a7bfb0
         
     | 
    
        data/LICENSE
    CHANGED
    
    
| 
         @@ -1,15 +1,11 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # ActsAsParanoid
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            [](https://travis-ci.org/ActsAsParanoid/acts_as_paranoid)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
       3 
5 
     | 
    
         
             
            A simple plugin which hides records instead of deleting them, being able to recover them.
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            **This branch targets Rails 3.2.** If you're working with another version, switch to the corresponding branch.
         
     | 
| 
       6 
8 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            ## Credits
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            This plugin was inspired by [acts_as_paranoid](http://github.com/technoweenie/acts_as_paranoid) and [acts_as_active](http://github.com/fernandoluizao/acts_as_active).
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
            While porting it to Rails 3, I decided to apply the ideas behind those plugins to an unified solution while removing a **lot** of the complexity found in them. I eventually ended up writing a new plugin from scratch.
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
9 
     | 
    
         
             
            ## Usage
         
     | 
| 
       14 
10 
     | 
    
         | 
| 
       15 
11 
     | 
    
         
             
            You can enable ActsAsParanoid like this:
         
     | 
| 
         @@ -186,29 +182,34 @@ Paranoiac.pretty.only_deleted.count #=> 1 
     | 
|
| 
       186 
182 
     | 
    
         
             
            Associations are also supported. From the simplest behaviors you'd expect to more nifty things like the ones mentioned previously or the usage of the `:with_deleted` option with `belongs_to`
         
     | 
| 
       187 
183 
     | 
    
         | 
| 
       188 
184 
     | 
    
         
             
            ```ruby
         
     | 
| 
       189 
     | 
    
         
            -
            class  
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
      
 185 
     | 
    
         
            +
            class Parent < ActiveRecord::Base
         
     | 
| 
      
 186 
     | 
    
         
            +
              has_many :children, :class_name => "ParanoiacChild"
         
     | 
| 
       191 
187 
     | 
    
         
             
            end
         
     | 
| 
       192 
188 
     | 
    
         | 
| 
       193 
189 
     | 
    
         
             
            class ParanoiacChild < ActiveRecord::Base
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
      
 190 
     | 
    
         
            +
              acts_as_paranoid
         
     | 
| 
      
 191 
     | 
    
         
            +
              belongs_to :parent
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
              # You may need to provide a foreign_key like this
         
     | 
| 
      
 194 
     | 
    
         
            +
              belongs_to :parent_including_deleted, :class_name => "Parent", foreign_key => 'parent_id', :with_deleted => true
         
     | 
| 
       196 
195 
     | 
    
         
             
            end
         
     | 
| 
       197 
196 
     | 
    
         | 
| 
       198 
     | 
    
         
            -
            parent =  
     | 
| 
      
 197 
     | 
    
         
            +
            parent = Parent.first
         
     | 
| 
       199 
198 
     | 
    
         
             
            child = parent.children.create
         
     | 
| 
       200 
199 
     | 
    
         
             
            parent.destroy
         
     | 
| 
       201 
200 
     | 
    
         | 
| 
       202 
201 
     | 
    
         
             
            child.parent #=> nil
         
     | 
| 
       203 
     | 
    
         
            -
            child. 
     | 
| 
      
 202 
     | 
    
         
            +
            child.parent_including_deleted #=> Parent (it works!)
         
     | 
| 
       204 
203 
     | 
    
         
             
            ```
         
     | 
| 
       205 
204 
     | 
    
         | 
| 
       206 
205 
     | 
    
         
             
            ## Caveats
         
     | 
| 
       207 
206 
     | 
    
         | 
| 
       208 
207 
     | 
    
         
             
            Watch out for these caveats:
         
     | 
| 
       209 
208 
     | 
    
         | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
       210 
210 
     | 
    
         
             
            -   You cannot use scopes named `with_deleted` and `only_deleted`
         
     | 
| 
       211 
211 
     | 
    
         
             
            -   You cannot use scopes named `deleted_inside_time_window`, `deleted_before_time`, `deleted_after_time` **if** your paranoid column's type is `time`
         
     | 
| 
      
 212 
     | 
    
         
            +
            -   You cannot name association `*_with_deleted`
         
     | 
| 
       212 
213 
     | 
    
         
             
            -   `unscoped` will return all records, deleted or not
         
     | 
| 
       213 
214 
     | 
    
         | 
| 
       214 
215 
     | 
    
         
             
            # Support
         
     | 
| 
         @@ -219,20 +220,21 @@ This gem supports the most recent versions of Rails and Ruby. 
     | 
|
| 
       219 
220 
     | 
    
         | 
| 
       220 
221 
     | 
    
         
             
            For Rails 3.2 check the README at the [rails3.2](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.2) branch and add this to your Gemfile:
         
     | 
| 
       221 
222 
     | 
    
         | 
| 
       222 
     | 
    
         
            -
             
     | 
| 
      
 223 
     | 
    
         
            +
                gem "acts_as_paranoid", "~> 0.4.0"
         
     | 
| 
       223 
224 
     | 
    
         | 
| 
       224 
225 
     | 
    
         
             
            For Rails 3.1 check the README at the [rails3.1](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.1) branch and add this to your Gemfile:
         
     | 
| 
       225 
226 
     | 
    
         | 
| 
       226 
     | 
    
         
            -
             
     | 
| 
      
 227 
     | 
    
         
            +
                gem "rails3_acts_as_paranoid", "~>0.1.4"
         
     | 
| 
       227 
228 
     | 
    
         | 
| 
       228 
229 
     | 
    
         
             
            For Rails 3.0 check the README at the [rails3.0](https://github.com/goncalossilva/rails3_acts_as_paranoid/tree/rails3.0) branch and add this to your Gemfile:
         
     | 
| 
       229 
230 
     | 
    
         | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
      
 231 
     | 
    
         
            +
                gem "rails3_acts_as_paranoid", "~>0.0.9"
         
     | 
| 
       231 
232 
     | 
    
         | 
| 
       232 
233 
     | 
    
         | 
| 
       233 
234 
     | 
    
         
             
            ## Ruby
         
     | 
| 
       234 
235 
     | 
    
         | 
| 
       235 
     | 
    
         
            -
            This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode). 
     | 
| 
      
 236 
     | 
    
         
            +
            This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode).
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
       236 
238 
     | 
    
         | 
| 
       237 
239 
     | 
    
         
             
            # Acknowledgements
         
     | 
| 
       238 
240 
     | 
    
         | 
| 
         @@ -244,4 +246,11 @@ This gem is tested on Ruby 1.9, JRuby and Rubinius (both in 1.9 mode). It *might 
     | 
|
| 
       244 
246 
     | 
    
         
             
            * To [Craig Walker](https://github.com/softcraft-development) for Rails 3.1 support and fixing various pending issues
         
     | 
| 
       245 
247 
     | 
    
         
             
            * To [Charles G.](https://github.com/chuckg) for Rails 3.2 support and for making a desperately needed global code refactoring
         
     | 
| 
       246 
248 
     | 
    
         | 
| 
       247 
     | 
    
         
            -
             
     | 
| 
      
 249 
     | 
    
         
            +
            ## Credits
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
            This plugin was inspired by [acts_as_paranoid](http://github.com/technoweenie/acts_as_paranoid) and [acts_as_active](http://github.com/fernandoluizao/acts_as_active).
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
            While porting it to Rails 3, I decided to apply the ideas behind those plugins to an unified solution while removing a **lot** of the complexity found in them. I eventually ended up writing a new plugin from scratch.
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
      
 256 
     | 
    
         
            +
            Copyright © 2014 Zachary Scott, Gonçalo Silva, Rick Olson, released under the MIT license
         
     | 
| 
         @@ -94,7 +94,7 @@ module ActsAsParanoid 
     | 
|
| 
       94 
94 
     | 
    
         
             
                    run_callbacks :destroy do
         
     | 
| 
       95 
95 
     | 
    
         
             
                      destroy_dependent_associations!
         
     | 
| 
       96 
96 
     | 
    
         
             
                      # Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`.
         
     | 
| 
       97 
     | 
    
         
            -
                      self.class.delete_all!(Hash[[Array(self.class.primary_key), Array(self.id)].transpose])
         
     | 
| 
      
 97 
     | 
    
         
            +
                      self.class.delete_all!(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted?
         
     | 
| 
       98 
98 
     | 
    
         
             
                      self.paranoid_value = self.class.delete_now_value
         
     | 
| 
       99 
99 
     | 
    
         
             
                      freeze
         
     | 
| 
       100 
100 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -106,7 +106,7 @@ module ActsAsParanoid 
     | 
|
| 
       106 
106 
     | 
    
         
             
                    with_transaction_returning_status do
         
     | 
| 
       107 
107 
     | 
    
         
             
                      run_callbacks :destroy do
         
     | 
| 
       108 
108 
     | 
    
         
             
                        # Handle composite keys, otherwise we would just use `self.class.primary_key.to_sym => self.id`.
         
     | 
| 
       109 
     | 
    
         
            -
                        self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose])
         
     | 
| 
      
 109 
     | 
    
         
            +
                        self.class.delete_all(Hash[[Array(self.class.primary_key), Array(self.id)].transpose]) if persisted?
         
     | 
| 
       110 
110 
     | 
    
         
             
                        self.paranoid_value = self.class.delete_now_value
         
     | 
| 
       111 
111 
     | 
    
         
             
                        self
         
     | 
| 
       112 
112 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -134,17 +134,17 @@ module ActsAsParanoid 
     | 
|
| 
       134 
134 
     | 
    
         | 
| 
       135 
135 
     | 
    
         
             
                def recover_dependent_associations(window, options)
         
     | 
| 
       136 
136 
     | 
    
         
             
                  self.class.dependent_associations.each do |reflection|
         
     | 
| 
       137 
     | 
    
         
            -
                    next unless reflection. 
     | 
| 
      
 137 
     | 
    
         
            +
                    next unless (klass = get_reflection_class(reflection)).paranoid?
         
     | 
| 
       138 
138 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
                    scope =  
     | 
| 
      
 139 
     | 
    
         
            +
                    scope = klass.only_deleted
         
     | 
| 
       140 
140 
     | 
    
         | 
| 
       141 
141 
     | 
    
         
             
                    # Merge in the association's scope
         
     | 
| 
       142 
142 
     | 
    
         
             
                    scope = scope.merge(association(reflection.name).association_scope)
         
     | 
| 
       143 
143 
     | 
    
         | 
| 
       144 
144 
     | 
    
         
             
                    # We can only recover by window if both parent and dependant have a
         
     | 
| 
       145 
145 
     | 
    
         
             
                    # paranoid column type of :time.
         
     | 
| 
       146 
     | 
    
         
            -
                    if self.class.paranoid_column_type == :time &&  
     | 
| 
       147 
     | 
    
         
            -
                      scope = scope.merge( 
     | 
| 
      
 146 
     | 
    
         
            +
                    if self.class.paranoid_column_type == :time && klass.paranoid_column_type == :time
         
     | 
| 
      
 147 
     | 
    
         
            +
                      scope = scope.merge(klass.deleted_inside_time_window(paranoid_value, window))
         
     | 
| 
       148 
148 
     | 
    
         
             
                    end
         
     | 
| 
       149 
149 
     | 
    
         | 
| 
       150 
150 
     | 
    
         
             
                    scope.each do |object|
         
     | 
| 
         @@ -155,9 +155,9 @@ module ActsAsParanoid 
     | 
|
| 
       155 
155 
     | 
    
         | 
| 
       156 
156 
     | 
    
         
             
                def destroy_dependent_associations!
         
     | 
| 
       157 
157 
     | 
    
         
             
                  self.class.dependent_associations.each do |reflection|
         
     | 
| 
       158 
     | 
    
         
            -
                    next unless reflection. 
     | 
| 
      
 158 
     | 
    
         
            +
                    next unless (klass = get_reflection_class(reflection)).paranoid?
         
     | 
| 
       159 
159 
     | 
    
         | 
| 
       160 
     | 
    
         
            -
                    scope =  
     | 
| 
      
 160 
     | 
    
         
            +
                    scope = klass.only_deleted
         
     | 
| 
       161 
161 
     | 
    
         | 
| 
       162 
162 
     | 
    
         
             
                    # Merge in the association's scope
         
     | 
| 
       163 
163 
     | 
    
         
             
                    scope = scope.merge(association(reflection.name).association_scope)
         
     | 
| 
         @@ -177,6 +177,14 @@ module ActsAsParanoid 
     | 
|
| 
       177 
177 
     | 
    
         | 
| 
       178 
178 
     | 
    
         
             
                private
         
     | 
| 
       179 
179 
     | 
    
         | 
| 
      
 180 
     | 
    
         
            +
                def get_reflection_class(reflection)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  if reflection.macro == :belongs_to && reflection.options.include?(:polymorphic)
         
     | 
| 
      
 182 
     | 
    
         
            +
                    self.send(reflection.foreign_type).constantize
         
     | 
| 
      
 183 
     | 
    
         
            +
                  else
         
     | 
| 
      
 184 
     | 
    
         
            +
                    reflection.klass
         
     | 
| 
      
 185 
     | 
    
         
            +
                  end
         
     | 
| 
      
 186 
     | 
    
         
            +
                end
         
     | 
| 
      
 187 
     | 
    
         
            +
             
     | 
| 
       180 
188 
     | 
    
         
             
                def paranoid_value=(value)
         
     | 
| 
       181 
189 
     | 
    
         
             
                  self.send("#{self.class.paranoid_column}=", value)
         
     | 
| 
       182 
190 
     | 
    
         
             
                end
         
     | 
| 
         @@ -5,7 +5,7 @@ module ActsAsParanoid 
     | 
|
| 
       5 
5 
     | 
    
         
             
                    def paranoid?
         
     | 
| 
       6 
6 
     | 
    
         
             
                      klass.try(:paranoid?) ? true : false
         
     | 
| 
       7 
7 
     | 
    
         
             
                    end
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
       9 
9 
     | 
    
         
             
                    def paranoid_deletion_attributes
         
     | 
| 
       10 
10 
     | 
    
         
             
                      { klass.paranoid_column => klass.delete_now_value }
         
     | 
| 
       11 
11 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -18,7 +18,7 @@ module ActsAsParanoid 
     | 
|
| 
       18 
18 
     | 
    
         
             
                        orig_delete_all
         
     | 
| 
       19 
19 
     | 
    
         
             
                      end
         
     | 
| 
       20 
20 
     | 
    
         
             
                    end
         
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
       22 
22 
     | 
    
         
             
                    def delete_all(conditions = nil)
         
     | 
| 
       23 
23 
     | 
    
         
             
                      if paranoid?
         
     | 
| 
       24 
24 
     | 
    
         
             
                        update_all(paranoid_deletion_attributes, conditions)
         
     | 
    
        data/lib/acts_as_paranoid.rb
    CHANGED
    
    | 
         @@ -1,27 +1,23 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'active_record/base'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'active_record/relation'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'active_record/callbacks'
         
     | 
| 
       4 
1 
     | 
    
         
             
            require 'acts_as_paranoid/core'
         
     | 
| 
       5 
2 
     | 
    
         
             
            require 'acts_as_paranoid/associations'
         
     | 
| 
       6 
3 
     | 
    
         
             
            require 'acts_as_paranoid/validations'
         
     | 
| 
       7 
4 
     | 
    
         
             
            require 'acts_as_paranoid/relation'
         
     | 
| 
       8 
5 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
6 
     | 
    
         
             
            module ActsAsParanoid
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
       12 
8 
     | 
    
         
             
              def paranoid?
         
     | 
| 
       13 
9 
     | 
    
         
             
                self.included_modules.include?(ActsAsParanoid::Core)
         
     | 
| 
       14 
10 
     | 
    
         
             
              end
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
       16 
12 
     | 
    
         
             
              def validates_as_paranoid
         
     | 
| 
       17 
13 
     | 
    
         
             
                include ActsAsParanoid::Validations
         
     | 
| 
       18 
14 
     | 
    
         
             
              end
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       20 
16 
     | 
    
         
             
              def acts_as_paranoid(options = {})
         
     | 
| 
       21 
17 
     | 
    
         
             
                raise ArgumentError, "Hash expected, got #{options.class.name}" if not options.is_a?(Hash) and not options.empty?
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
       23 
19 
     | 
    
         
             
                class_attribute :paranoid_configuration, :paranoid_column_reference
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       25 
21 
     | 
    
         
             
                self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes }
         
     | 
| 
       26 
22 
     | 
    
         
             
                self.paranoid_configuration.merge!({ :deleted_value => "deleted" }) if options[:column_type] == "string"
         
     | 
| 
       27 
23 
     | 
    
         
             
                self.paranoid_configuration.merge!(options) # user options
         
     | 
| 
         @@ -29,11 +25,11 @@ module ActsAsParanoid 
     | 
|
| 
       29 
25 
     | 
    
         
             
                raise ArgumentError, "'time', 'boolean' or 'string' expected for :column_type option, got #{paranoid_configuration[:column_type]}" unless ['time', 'boolean', 'string'].include? paranoid_configuration[:column_type]
         
     | 
| 
       30 
26 
     | 
    
         | 
| 
       31 
27 
     | 
    
         
             
                self.paranoid_column_reference = "#{self.table_name}.#{paranoid_configuration[:column]}"
         
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       33 
29 
     | 
    
         
             
                return if paranoid?
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
       35 
31 
     | 
    
         
             
                include ActsAsParanoid::Core
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
       37 
33 
     | 
    
         
             
                # Magic!
         
     | 
| 
       38 
34 
     | 
    
         
             
                default_scope { where(paranoid_default_scope_sql) }
         
     | 
| 
       39 
35 
     | 
    
         | 
| 
         @@ -42,8 +38,8 @@ module ActsAsParanoid 
     | 
|
| 
       42 
38 
     | 
    
         
             
                    deleted_after_time((time - window)).deleted_before_time((time + window))
         
     | 
| 
       43 
39 
     | 
    
         
             
                  }
         
     | 
| 
       44 
40 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                  scope :deleted_after_time, lambda  { |time| where("#{paranoid_column} > ?", time) }
         
     | 
| 
       46 
     | 
    
         
            -
                  scope :deleted_before_time, lambda { |time| where("#{paranoid_column} < ?", time) }
         
     | 
| 
      
 41 
     | 
    
         
            +
                  scope :deleted_after_time, lambda  { |time| where("#{self.table_name}.#{paranoid_column} > ?", time) }
         
     | 
| 
      
 42 
     | 
    
         
            +
                  scope :deleted_before_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} < ?", time) }
         
     | 
| 
       47 
43 
     | 
    
         
             
                end
         
     | 
| 
       48 
44 
     | 
    
         
             
              end
         
     | 
| 
       49 
45 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,222 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'test_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class AssociationsTest < ParanoidBaseTest
         
     | 
| 
      
 4 
     | 
    
         
            +
              def test_removal_with_associations
         
     | 
| 
      
 5 
     | 
    
         
            +
                # This test shows that the current implementation doesn't handle
         
     | 
| 
      
 6 
     | 
    
         
            +
                # assciation deletion correctly (when hard deleting via parent-object)
         
     | 
| 
      
 7 
     | 
    
         
            +
                paranoid_company_1 = ParanoidDestroyCompany.create! :name => "ParanoidDestroyCompany #1"
         
     | 
| 
      
 8 
     | 
    
         
            +
                paranoid_company_2 = ParanoidDeleteCompany.create! :name => "ParanoidDestroyCompany #1"
         
     | 
| 
      
 9 
     | 
    
         
            +
                paranoid_company_1.paranoid_products.create! :name => "ParanoidProduct #1"
         
     | 
| 
      
 10 
     | 
    
         
            +
                paranoid_company_2.paranoid_products.create! :name => "ParanoidProduct #2"
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                assert_equal 1, ParanoidDestroyCompany.count
         
     | 
| 
      
 13 
     | 
    
         
            +
                assert_equal 1, ParanoidDeleteCompany.count
         
     | 
| 
      
 14 
     | 
    
         
            +
                assert_equal 2, ParanoidProduct.count
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                ParanoidDestroyCompany.first.destroy
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert_equal 0, ParanoidDestroyCompany.count
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert_equal 1, ParanoidProduct.count
         
     | 
| 
      
 19 
     | 
    
         
            +
                assert_equal 1, ParanoidDestroyCompany.with_deleted.count
         
     | 
| 
      
 20 
     | 
    
         
            +
                assert_equal 2, ParanoidProduct.with_deleted.count
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                ParanoidDestroyCompany.with_deleted.first.destroy!
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert_equal 0, ParanoidDestroyCompany.count
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert_equal 1, ParanoidProduct.count
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert_equal 0, ParanoidDestroyCompany.with_deleted.count
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert_equal 1, ParanoidProduct.with_deleted.count
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                ParanoidDeleteCompany.with_deleted.first.destroy!
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert_equal 0, ParanoidDeleteCompany.count
         
     | 
| 
      
 30 
     | 
    
         
            +
                assert_equal 0, ParanoidProduct.count
         
     | 
| 
      
 31 
     | 
    
         
            +
                assert_equal 0, ParanoidDeleteCompany.with_deleted.count
         
     | 
| 
      
 32 
     | 
    
         
            +
                assert_equal 0, ParanoidProduct.with_deleted.count
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def test_belongs_to_with_deleted
         
     | 
| 
      
 36 
     | 
    
         
            +
                paranoid_time = ParanoidTime.first
         
     | 
| 
      
 37 
     | 
    
         
            +
                paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!')
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                paranoid_time.destroy
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time(true)
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_with_deleted(true)
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              def test_belongs_to_polymorphic_with_deleted
         
     | 
| 
      
 49 
     | 
    
         
            +
                paranoid_time = ParanoidTime.first
         
     | 
| 
      
 50 
     | 
    
         
            +
                paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => paranoid_time)
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                paranoid_time.destroy
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time(true)
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert_equal paranoid_time, paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              def test_belongs_to_nil_polymorphic_with_deleted
         
     | 
| 
      
 62 
     | 
    
         
            +
                paranoid_time = ParanoidTime.first
         
     | 
| 
      
 63 
     | 
    
         
            +
                paranoid_has_many_dependant = ParanoidHasManyDependant.create!(:name => 'dependant!', :paranoid_time_polymorphic_with_deleted => nil)
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time
         
     | 
| 
      
 66 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                paranoid_time.destroy
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time(true)
         
     | 
| 
      
 71 
     | 
    
         
            +
                assert_nil paranoid_has_many_dependant.paranoid_time_polymorphic_with_deleted(true)
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              def test_belongs_to_options
         
     | 
| 
      
 75 
     | 
    
         
            +
                paranoid_time = ParanoidHasManyDependant.reflections[:paranoid_time]
         
     | 
| 
      
 76 
     | 
    
         
            +
                assert_equal :belongs_to, paranoid_time.macro
         
     | 
| 
      
 77 
     | 
    
         
            +
                assert_nil paranoid_time.options[:with_deleted]
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              def test_belongs_to_with_deleted_options
         
     | 
| 
      
 81 
     | 
    
         
            +
                paranoid_time_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_with_deleted]
         
     | 
| 
      
 82 
     | 
    
         
            +
                assert_equal :belongs_to, paranoid_time_with_deleted.macro
         
     | 
| 
      
 83 
     | 
    
         
            +
                assert paranoid_time_with_deleted.options[:with_deleted]
         
     | 
| 
      
 84 
     | 
    
         
            +
              end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
              def test_belongs_to_polymorphic_with_deleted_options
         
     | 
| 
      
 87 
     | 
    
         
            +
                paranoid_time_polymorphic_with_deleted = ParanoidHasManyDependant.reflections[:paranoid_time_polymorphic_with_deleted]
         
     | 
| 
      
 88 
     | 
    
         
            +
                assert_equal :belongs_to, paranoid_time_polymorphic_with_deleted.macro
         
     | 
| 
      
 89 
     | 
    
         
            +
                assert paranoid_time_polymorphic_with_deleted.options[:with_deleted]
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              def test_only_find_associated_records_when_finding_with_paranoid_deleted
         
     | 
| 
      
 93 
     | 
    
         
            +
                parent = ParanoidBelongsDependant.create
         
     | 
| 
      
 94 
     | 
    
         
            +
                child = ParanoidHasManyDependant.create
         
     | 
| 
      
 95 
     | 
    
         
            +
                parent.paranoid_has_many_dependants << child
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                unrelated_parent = ParanoidBelongsDependant.create
         
     | 
| 
      
 98 
     | 
    
         
            +
                unrelated_child = ParanoidHasManyDependant.create
         
     | 
| 
      
 99 
     | 
    
         
            +
                unrelated_parent.paranoid_has_many_dependants << unrelated_child
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                child.destroy
         
     | 
| 
      
 102 
     | 
    
         
            +
                assert_paranoid_deletion(child)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                assert_equal [child], parent.paranoid_has_many_dependants.with_deleted.to_a
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              def test_cannot_find_a_paranoid_deleted_many_many_association
         
     | 
| 
      
 108 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 109 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 110 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights.delete(right)
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                left.reload
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
         
     | 
| 
      
 117 
     | 
    
         
            +
                assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
         
     | 
| 
      
 118 
     | 
    
         
            +
                assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
              def test_cannot_find_a_paranoid_destroyed_many_many_association
         
     | 
| 
      
 122 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 123 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 124 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights.destroy(right)
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                left.reload
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                assert_equal [], left.paranoid_many_many_children, "Linking objects not deleted"
         
     | 
| 
      
 131 
     | 
    
         
            +
                assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not unlinked"
         
     | 
| 
      
 132 
     | 
    
         
            +
                assert_equal right, ParanoidManyManyParentRight.find(right.id), "Associated object deleted"
         
     | 
| 
      
 133 
     | 
    
         
            +
              end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
              def test_cannot_find_a_has_many_through_object_when_its_linking_object_is_paranoid_destroyed
         
     | 
| 
      
 136 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 137 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 138 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                child = left.paranoid_many_many_children.first
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                child.destroy
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                left.reload
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                assert_equal [], left.paranoid_many_many_parent_rights, "Associated objects not deleted"
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              def test_cannot_find_a_paranoid_deleted_model
         
     | 
| 
      
 150 
     | 
    
         
            +
                model = ParanoidBelongsDependant.create
         
     | 
| 
      
 151 
     | 
    
         
            +
                model.destroy
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                assert_raises ActiveRecord::RecordNotFound do
         
     | 
| 
      
 154 
     | 
    
         
            +
                  ParanoidBelongsDependant.find(model.id)
         
     | 
| 
      
 155 
     | 
    
         
            +
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              def test_bidirectional_has_many_through_association_clear_is_paranoid
         
     | 
| 
      
 159 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 160 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 161 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                child = left.paranoid_many_many_children.first
         
     | 
| 
      
 164 
     | 
    
         
            +
                assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
         
     | 
| 
      
 165 
     | 
    
         
            +
                assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights.clear
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                assert_paranoid_deletion(child)
         
     | 
| 
      
 170 
     | 
    
         
            +
              end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
              def test_bidirectional_has_many_through_association_destroy_is_paranoid
         
     | 
| 
      
 173 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 174 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 175 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                child = left.paranoid_many_many_children.first
         
     | 
| 
      
 178 
     | 
    
         
            +
                assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
         
     | 
| 
      
 179 
     | 
    
         
            +
                assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights.destroy(right)
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                assert_paranoid_deletion(child)
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              def test_bidirectional_has_many_through_association_delete_is_paranoid
         
     | 
| 
      
 187 
     | 
    
         
            +
                left = ParanoidManyManyParentLeft.create
         
     | 
| 
      
 188 
     | 
    
         
            +
                right = ParanoidManyManyParentRight.create
         
     | 
| 
      
 189 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights << right
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
      
 191 
     | 
    
         
            +
                child = left.paranoid_many_many_children.first
         
     | 
| 
      
 192 
     | 
    
         
            +
                assert_equal left, child.paranoid_many_many_parent_left, "Child's left parent is incorrect"
         
     | 
| 
      
 193 
     | 
    
         
            +
                assert_equal right, child.paranoid_many_many_parent_right, "Child's right parent is incorrect"
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                left.paranoid_many_many_parent_rights.delete(right)
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                assert_paranoid_deletion(child)
         
     | 
| 
      
 198 
     | 
    
         
            +
              end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
              def test_belongs_to_on_normal_model_is_paranoid
         
     | 
| 
      
 201 
     | 
    
         
            +
                not_paranoid = HasOneNotParanoid.create
         
     | 
| 
      
 202 
     | 
    
         
            +
                not_paranoid.paranoid_time = ParanoidTime.create
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                assert not_paranoid.save
         
     | 
| 
      
 205 
     | 
    
         
            +
                assert_not_nil not_paranoid.paranoid_time
         
     | 
| 
      
 206 
     | 
    
         
            +
              end
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
              def test_double_belongs_to_with_deleted
         
     | 
| 
      
 209 
     | 
    
         
            +
                not_paranoid = DoubleHasOneNotParanoid.create
         
     | 
| 
      
 210 
     | 
    
         
            +
                not_paranoid.paranoid_time = ParanoidTime.create
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                assert not_paranoid.save
         
     | 
| 
      
 213 
     | 
    
         
            +
                assert_not_nil not_paranoid.paranoid_time
         
     | 
| 
      
 214 
     | 
    
         
            +
              end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
              def test_mass_assignment_of_paranoid_column_enabled
         
     | 
| 
      
 217 
     | 
    
         
            +
                now = Time.now
         
     | 
| 
      
 218 
     | 
    
         
            +
                record = ParanoidTime.create! :name => 'Foo', :deleted_at => now
         
     | 
| 
      
 219 
     | 
    
         
            +
                assert_equal 'Foo', record.name
         
     | 
| 
      
 220 
     | 
    
         
            +
                assert_equal now, record.deleted_at
         
     | 
| 
      
 221 
     | 
    
         
            +
              end
         
     | 
| 
      
 222 
     | 
    
         
            +
            end
         
     |