How to query records that have an ActiveStorage attachment?

前端 未结 3 808
深忆病人
深忆病人 2020-12-18 21:02

Given a model with ActiveStorage

class User 
  has_one_attached :avatar
end

I can check whether a single user has an avatar



        
相关标签:
3条回答
  • 2020-12-18 21:20

    Convention for attachment association names

    Attachment associations are named using the following convention:

    <NAME OF ATTACHMENT>_attachment

    For example, if you have has_one_attached :avatar then the association name will be avatar_attachment.

    Querying for Active Storage attachments

    Now that you know how attachment associations are named, you can query them by using joins as you would any other Active Record association.

    For example, given the User class below

    class User
       has_one_attached :avatar
    end
    

    You can query for all User records that have that attachment as follows

    User.joins(:avatar_attachment)
    

    This performs an INNER JOIN which will only return records which have the attachment.

    You can query for all User records that DO NOT have that attachment like this

    User.
      left_joins(:avatar_attachment).
      group(:id).
      having("COUNT(active_storage_attachments) = 0")
    
    0 讨论(0)
  • 2020-12-18 21:24

    Slightly related, here is how to perform a search query on the attached records:

    def self.search_name(search)
      with_attached_attachment.
        references(:attachment_attachment).
        where(ActiveStorage::Blob.arel_table[:filename].matches("%#{search}%"))
    end
    

    You'll just have to update the with_attached_attachment and :attachment_attachment to reflect your attached model. In my case I have has_one_attached :attachment

    And for those wondering, the Arel #matches does not appear to be susceptible to SQL injection attacks.

    0 讨论(0)
  • 2020-12-18 21:37

    I wanted to know if a record has any attachments (I had multiple attachments say a passport and other docs for User) so I can display/hide a section in UI.

    Based on the answer here I've been able to add the following method to ApplicationRecord:

    def any_attached?
      ActiveStorage::Attachment.where(record_type: model_name.to_s, record_id: id).any?
    end
    

    Then you can use it like:

    User.last.any_attached?
    #=> true
    
    0 讨论(0)
提交回复
热议问题