pixelearth
pixelearth

Reputation: 14610

How do do a join on has_many_attached Active Storage association?

I would like to do a DB query that finds all records that have files attached.

class Departure 
  has_many_attached :pre_trip_documents
end

However this fails:

Departure.joins(:pre_trip_documents).to_sql => #ActiveRecord::ConfigurationError (Can't join 'Departure' to association named 'pre_trip_documents'; perhaps you misspelled it?)

Upvotes: 3

Views: 2563

Answers (2)

I faced a similar problem. Probably you have to check the blobs instead of the pre_trip_documents association

Adding

has_many :pre_trip_documents_attachments, class_name: 'ActiveStorage::Attachment'
has_many :pre_trip_documents_blobs, through: :pre_trip_documents_attachments, class_name: 'ActiveStorage::Blob', source: :blob

You will be able to do

Departure.joins(:pre_trip_documents_blobs)

To see those attachments

More about: https://edgeguides.rubyonrails.org/active_storage_overview.html

UPDATE

Looking on the blobs was the solution for the problem that I faced. But as @weilandia answer said, it will be better to check first the attachments

Departure.joins(:pre_trip_documents_attachments)

Upvotes: 0

weilandia
weilandia

Reputation: 577

You can do:

Departure.joins(:pre_trip_documents_attachments)

This will make more sense if you look at the source of has_many_attached, which you can find here.

To summarize, has_many_attached :pre_trip_documents results in:

has_many :"pre_trip_documents_attachments", -> { where(name: "pre_trip_documents") }, as: :record, class_name: "ActiveStorage::Attachment" ...

So calling Departure.joins(:pre_trip_documents_attachments) gives you:

SELECT "departures".* FROM "departures" INNER JOIN 
"active_storage_attachments" ON 
"active_storage_attachments"."record_id" = "departures"."id" AND 
"active_storage_attachments"."record_type" = 'Departure' AND 
"active_storage_attachments"."name" = 'pre_trip_documents'

Upvotes: 7

Related Questions