How to get list of ActiveStorage attributes (attachment names)?

Viewed 2081

For example I have model

class User < ApplicationRecord
  has_one_attached :avatar
  has_one_attached :diploma

  has_many_attached :photos
  has_many_attached :files
end

How to get lists of attachments names for some model (separately for has_one_attached and has_many_attached)?

[:avatar, :diploma] and [:photos, :files] in this case.

3 Answers

A solution that doesn't depend on naming conventions and will give you exactly what you need based on Rails own internals:

  • for has_one_attached
User
  .reflect_on_all_attachments
  .filter { |association| association.instance_of? ActiveStorage::Reflection::HasOneAttachedReflection }
  .map(&:name)
  • for has_many_attached
User
  .reflect_on_all_attachments
  .filter { |association| association.instance_of? ActiveStorage::Reflection::HasManyAttachedReflection }
  .map(&:name)

I don't know if there is a straightforward way, bud this should workaround (for already stored records):

ActiveStorage::Attachment.distinct.pluck(:record_type).map(&:underscore)


Starting from a model, this is a raw idea to be refined:

User.reflect_on_all_associations(:has_many).map { |e| e.name.to_s.split("_") }.select { |e| e.last == "attachments" }
User.reflect_on_all_associations(:has_one).map { |e| e.name.to_s.split("_") }.select { |e| e.last == "attachment" }

Note == "attachments" and == "attachment"

@iGian gave a great idea, but there is a problem in it.

If the attachment name contains the underscore(s), it will lead to an incorrect result.

So my solution is:

  • for has_many_attached
User.
  reflect_on_all_associations(:has_many).
  map { |reflection| reflection.name.to_s }.
  select { |name| name.match?(/_attachments/) }.
  map { |name| name.chomp('_attachments').to_sym }

#=> [:photos, :files]
  • for has_one_attached
User.
  reflect_on_all_associations(:has_one).
  map { |reflection| reflection.name.to_s }.
  select { |name| name.match?(/_attachment/) }.
  map { |name| name.chomp('_attachment').to_sym }

#=> [:avatar, :diploma]
Related