Paranoia Gem - joins with deleted items

4.1k Views Asked by At

I'm using Paranoia gem and now struggling with the problem. I need to joins has_many deleted items, but it returns not deleted only. My models:

class Mailing < ActiveRecord::Base

  acts_as_paranoid

  has_many :mailing_fields
  has_many :fields, through: :mailing_fields

end

class MailingField < ActiveRecord::

  belongs_to :mailing
  belongs_to :field

end

class Field < ActiveRecord::Base

  has_many :mailing_fields, dependent: :destroy
  has_many :mailings, through: :mailing_fields

end

Query I'm running which should return mailings with deleted items:

Field.joins(:mailings).where('mailings.id = ?', mailing_id)
6

There are 6 best solutions below

0
On BEST ANSWER

The paranoid gem sets a default scope of only including non-deleted items in queries. The workaround would be:

Field.joins(:mailings).where('mailings.id = ? AND mailings.deleted_at IS NOT NULL', mailing_id)
0
On

The only working solution I've found so far is to manually specify the JOIN:

Field.joins('INNER JOIN "mailings" ON "mailings"."id" = "fields"."mailing_id"')
     .where('mailings.id = ?', mailing_id)
0
On

You could remove the scope in your query as such:

Field.joins(:mailings).where("mailings.deleted_at != :deleted_status OR mailings.deleted_at = :deleted_status", deleted_status: nil).where(mailings: { id: mailing_id })

OR since you're trying to fetch the Field which seems to be a many to many relationship, I'd prefer to invert the query as such:

Mailing.unscoped.joins(:fields).find(mailing_id).fields

Let me know if i was able to help.

1
On

Paranoid gem has built-in scope to access deleted items: with_deleted.

Mailing.with_deleted.joins(:fields).where(id: mailing_id)
0
On

unscoped also accepts a block, so you you can do the following:

Mailing.unscoped do
  Field.joins(:mailings).where('mailings.id = ?', mailing_id)
end

See: https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html#method-i-unscoped

2
On

I might be a bit too late to the party, but this can help if someone stumbles upon this problem.

You can create an additional association between parent and child to include the deleted records as well.

In context of the question asked,

class Field < ActiveRecord::Base
  has_many :mailing_fields, dependent: :destroy
  has_many :mailing_fields_with_deleted, -> { with_deleted }
 
  has_many :mailings, through: :mailing_fields
  has_many :mailings_with_deleted, through: :mailing_fields_with_deleted
end

and then use this relation: Field.joins(:mailings_with_deleted).where('mailings.id = ?', mailing_id)