Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List ActiveStorage attachments indirectly related to model

I am new to Rails and am trying to understand how ActiveStorage works.

The app has the following models:

class Client < ApplicationRecord
    has_many :jobs
    has_many :messages
end
class Job < ApplicationRecord
    belongs_to :client
    has_many_attached :images
end
class Message < ApplicationRecord
    belongs_to :client
    has_many_attached :images
end

In the database I can see the polymorphic relationship and I can also understand what SQL query would get me the desired results.

However I was wondering if there is an idiomatic and efficient way to retrieve all the attachments related to a client?

like image 779
Celso Avatar asked Sep 10 '18 13:09

Celso


People also ask

What is active storage attachment?

1 What is Active Storage? Active Storage facilitates uploading files to a cloud storage service like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage and attaching those files to Active Record objects.

How active storage works in Rails?

Active Storage uses two tables in your application's database named active_storage_blobs and active_storage_attachments . After creating a new application (or upgrading your application to Rails 5.2), run rails active_storage:install to generate a migration that creates these tables.

What is active storage blob?

A blob is a record that contains the metadata about a file and a key for where that file resides on the service. Blobs can be created in two ways: Subsequent to the file being uploaded server-side to the service via create_after_upload!.

What is the relationship between attachments and blobs in ActiveStorage?

Under the covers, this relationship is implemented as a has_many association to a ActiveStorage::Attachment record and a has_many-through association to a ActiveStorage::Blob record. These associations are available as photos_attachments and photos_blobs.

What is attachments column in active storage?

Specifies the relation between multiple attachments and the model. There are no columns defined on the model side, Active Storage takes care of the mapping between your records and the attachments. To avoid N+1 queries, you can include the attached blobs in your query like so:

How to avoid n+1 queries with attached blobs in ActiveStorage?

To avoid N+1 queries, you can include the attached blobs in your query like so: Under the covers, this relationship is implemented as a has_many association to a ActiveStorage::Attachment record and a has_many-through association to a ActiveStorage::Blob record.

What happens to attachments when a record is deleted from ActiveStorage?

The system has been designed to having you go through the ActiveStorage::Attached::Many proxy that provides the dynamic proxy to the associations and factory methods, like #attach. If the :dependent option isn't set, all the attachments will be purged (i.e. destroyed) whenever the record is destroyed.


1 Answers

Querying attachments associated with a given record

You can query for attachments directly using the ActiveStorage::Attachment class. The record attribute is the polymorphic association which joins to the attached class.

Here’s an example

ActiveStorage::Attachment.where(record: Job.first)

Querying attachments associated with a set of records

You can also pass a set of records to the record option

ActiveStorage::Attachment.where(record: Job.all)

Querying attachments associated with multiple sets of records

You can find attachments associated with multiple sets of records using or

ActiveStorage::Attachment.where(record: Job.all).or(ActiveStorage::Attachment.where(record: Message.all))

Putting it together...

To find all the attachments associated with multiple sets of records associated with a given record

client = Client.first
ActiveStorage::Attachment.where(record: client.jobs).or(ActiveStorage::Attachment.where(record: client.messages))

It’s not pretty, but it’s efficient. All the querying is done via Active Record which means it happens in a single SQL statement and doesn’t require loading any objects into memory.

like image 50
Carlos Ramirez III Avatar answered Oct 20 '22 05:10

Carlos Ramirez III