Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting paranoia deleted objects through polymorphic relation in Rails 3

I have an Audit class which is used to store action, by and on attributes.

class Audit < ActiveRecord::Base
  attr_accessible :activity
  belongs_to :by, :polymorphic => true
  belongs_to :on, :polymorphic => true
  attr_accessible :by, :on
end

The polymorphic association for :by and :on is used to store any kind of objects which should be audited. Mainly because polymorphic is broken down into type and id in the schema and thus should be able to store all my model objects.

  create_table "audits", :force => true do |t|
    t.string   "activity"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
    t.integer  "on_id"
    t.string   "on_type"
    t.integer  "by_id"
    t.string   "by_type"
  end

The problem I'm having comes from that all of the objects being audited are also using the paranoia gem. The paranoia gem introduces a deleted_at column in each models table which is checked for every query on that model through its default_scope which is set to something like "where(deleted_at is null)". The paranoia gem also provides a method .with_deleted which allows a direct query by turning of the default_scope and as a result also return objects which have beend paranoid / soft deleted.

However if I have any items that are deleted and I try to get all my Audited items listed using.

Audit.all

I can't figure out how to tell Rails to run the lookup query for each polymorphic :by and :on object adding the .with_deleted call. My guess is that rails looks up the the object of a polymorphic relation by

eval(type).find(id)

Which in my case would give me the object with the default_scope of the paranoia gem applied.

I have tried to override self.find_by_sql in Audit but with no luck. I get stuck in some Arel methods which I need to read up on more before I can move on.

I see the following solutions but I can't figure out how to do them.

  1. Overwrite the polymorphic lookup. How?
  2. Get the raw SQL as string before it's evaluated and sub/gsub the Where deleted_at is null part.

Any and all suggestions on how to approach this would be greatly appreciated.

like image 247
zmalex Avatar asked Nov 25 '12 21:11

zmalex


1 Answers

Try this:

def on!
  if on_type && on_id
    on_type.constantize.with_deleted.find(on_id)
  end
end

This will raise an ActiveRecord::RecordNotFound error if the record has been truly deleted, but otherwise will return the "on" object even if it is marked as deleted.

like image 83
Matt Connolly Avatar answered Oct 24 '22 03:10

Matt Connolly