Module: IsParanoid::InstanceMethods

Defined in:
lib/is_paranoid.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



157
158
159
160
161
162
163
164
165
# File 'lib/is_paranoid.rb', line 157

def self.included(base)
  base.class_eval do
    unless method_defined? :method_missing
      def method_missing(meth, *args, &block); super; end
    end
    alias_method :old_method_missing, :method_missing
    alias_method :method_missing, :is_paranoid_method_missing
  end
end

Instance Method Details

#destroyObject

Override the default destroy to allow us to flag deleted_at. This preserves the before_destroy and after_destroy callbacks. Because this is also called internally by Model.destroy_all and the Model.destroy(id), we don’t need to specify those methods separately.



225
226
227
228
229
230
# File 'lib/is_paranoid.rb', line 225

def destroy
  return false if callback(:before_destroy) == false
  result = destroy_without_callbacks
  callback(:after_destroy)
  self
end

#destroy_without_callbacksObject

Mark the model deleted_at as now.



212
213
214
215
216
217
218
# File 'lib/is_paranoid.rb', line 212

def destroy_without_callbacks
  self.class.update_all(
    "#{destroyed_field} = #{self.class.connection.quote(( field_destroyed.respond_to?(:call) ? field_destroyed.call : field_destroyed))}",
    self.class.primary_key.to_sym => self.id
  )
  self
end

#is_paranoid_method_missing(name, *args, &block) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/is_paranoid.rb', line 167

def is_paranoid_method_missing name, *args, &block
  # if we're trying for a _____with_destroyed method
  # and we can respond to the _____ method
  # and we have an association by the name of _____
  if name.to_s =~ /^(.*)(_with_destroyed)$/ and
      self.respond_to?($1) and
      (assoc = self.class.reflect_on_all_associations.detect{|a| a.name.to_s == $1})

    parent_klass = Object.module_eval("::#{assoc.class_name}", __FILE__, __LINE__)

    self.class.send(
      :include,
      Module.new {
    if assoc.macro.to_s =~ /^has/
      parent_method = assoc.macro.to_s =~ /^has_one/ ? 'first_with_destroyed' : 'all_with_destroyed'
                                                  # Example:
         define_method name do |*args|               # def android_with_destroyed
           parent_klass.send("#{parent_method}",     #   Android.all_with_destroyed(
             :conditions => {                        #     :conditions => {
               assoc.primary_key_name =>             #       :person_id =>
                 self.send(parent_klass.primary_key) #         self.send(:id)
             }                                       #     }
           )                                         #   )
         end                                         # end
  
    else
                                                      # Example:
         define_method name do |*args|               # def android_with_destroyed
           parent_klass.first_with_destroyed(        #   Android.first_with_destroyed(
             :conditions => {                        #     :conditions => {
               parent_klass.primary_key =>           #       :id =>
                 self.send(assoc.primary_key_name)   #         self.send(:android_id)
             }                                       #     }
           )                                         #   )
         end                                         # end
    end
      }
    )
    self.send(name, *args, &block)
  else
    old_method_missing(name, *args, &block)
  end
end

#restore(options = {}) ⇒ Object

Set deleted_at flag on a model to field_not_destroyed, effectively undoing the soft-deletion.



234
235
236
237
# File 'lib/is_paranoid.rb', line 234

def restore(options = {})
  self.class.restore(id, options)
  self
end