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?
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.
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.
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!.
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.
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:
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.
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.
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)
You can also pass a set of records to the record
option
ActiveStorage::Attachment.where(record: Job.all)
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))
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With