Acts As Paranoid - Has One With Deleted
May 25th, 2007
Out of the box acts_as_paranoid comes with the ability to define a belongs_to relationship as including deleted records (although to get it to work you need to add require File.dirname(FILE) + ’/lib/caboose/acts/belongs_to_with_deleted_association’ to the init.rb file):
class ModelA < ActiveRecord::Base belongs_to :model_b, :with_deleted => true end
This works quite nicely for that ModelA, but what happens if you want to include the deleted ModelA’s from ModelB through a has_one relationship…... its falls over. However that is easily fixed.
Simply create a new file in the lib/caboose/acts directory called has_one_with_deleted_association.rb and paste in the following:
module Caboose # :nodoc:
module Acts # :nodoc:
class HasOneWithDeletedAssociation < ActiveRecord::Associations::HasOneAssociation
private
def find_target
@reflection.klass.find_with_deleted(:first,
:conditions => @finder_sql,
:order => @reflection.options[:order],
:include => @reflection.options[:include]
)
end
end
end
end
Then open up the init.rb file and change the contents to match:
require File.dirname(__FILE__) + '/lib/caboose/acts/belongs_to_with_deleted_association'
require File.dirname(__FILE__) + '/lib/caboose/acts/has_one_with_deleted_association'
class << ActiveRecord::Base
def belongs_to_with_deleted(association_id, options = {})
with_deleted = options.delete :with_deleted
returning belongs_to_without_deleted(association_id, options) do
if with_deleted
reflection = reflect_on_association(association_id)
association_accessor_methods(reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
association_constructor_method(:build, reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
association_constructor_method(:create, reflection, Caboose::Acts::BelongsToWithDeletedAssociation)
end
end
end
alias_method_chain :belongs_to, :deleted
def has_one_with_deleted(association_id, options = {})
with_deleted = options.delete :with_deleted
returning has_one_without_deleted(association_id, options) do
if with_deleted
reflection = reflect_on_association(association_id)
association_accessor_methods(reflection, Caboose::Acts::HasOneWithDeletedAssociation)
association_constructor_method(:build, reflection, Caboose::Acts::HasOneWithDeletedAssociation)
association_constructor_method(:create, reflection, Caboose::Acts::HasOneWithDeletedAssociation)
end
end
end
alias_method_chain :has_one, :deleted
end
ActiveRecord::Base.send :include, Caboose::Acts::Paranoid
Voila, you can now say:
class ModelB < ActiveRecord::Base has_one :model_a, :with_deleted => true end
There is every chance this is a little hacky, but it seems to be working for me at the mo.