web-dev-qa-db-ja.com

ActiveStorage添付ファイルのあるレコードをクエリする方法は?

ActiveStorageを使用したモデルを考える

class User 
  has_one_attached :avatar
end

1人のユーザーがアバターを持っているかどうかを確認できます

@user.avatar.attached? 

しかし、どのようにして、添付ファイルを持つすべてのユーザーのコレクションを返すことができますか?

joinsを使用して添付ファイルのあるすべてのユーザーを取得しようとしましたが、これはblobまたは添付ファイルテーブルのいずれでも機能しないようです。または、構文が正しくありません。

私は何か明白なものを見落としていると確信しています。次のように何かを行うことは可能ですか?

User.where(attached_avatar: nil)

もしそうなら、これはどこに文書化されていますか?

10
Andy Harvey

添付ファイル関連付け名の規則

添付ファイルの関連付けは、次の規則に従って命名されます。

<NAME OF ATTACHMENT>_attachment

たとえば、has_one_attached :avatarがある場合、関連付け名はavatar_attachmentになります。

Active Storageアタッチメントのクエリ

添付ファイルの関連付けの名前がわかったので、他のアクティブレコードの関連付けと同じように、joinsを使用してそれらをクエリできます。

たとえば、以下のUserクラスがあるとします

class User
   has_one_attached :avatar
end

次のようにその添付ファイルを持つすべてのUserレコードのクエリを実行できます

User.joins(:avatar_attachment)

これは、添付ファイルを持つレコードのみを返すINNER JOINを実行します。

次のようにすることができますその添付ファイルがないすべてのUserレコードのクエリこのように

User.
  left_joins(:avatar_attachment).
  group(:id).
  having("COUNT(active_storage_attachments) = 0")
14

レコードに添付ファイルがあるかどうかを知りたいので(UIでセクションを表示/非表示にできるように、パスポートやUserのその他のドキュメントなど、複数の添付ファイルがありました)。

答えに基づいて ここApplicationRecordに次のメソッドを追加できました:

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

その後、次のように使用できます。

User.last.any_attached?
#=> true
2
M-Dahab

少し関連していますが、添付されたレコードに対して検索クエリを実行する方法を次に示します。

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

アタッチされたモデルを反映するには、with_attached_attachment:attachment_attachmentを更新するだけです。私の場合、私はhas_one_attached :attachmentを持っています

そして不思議に思う人にとって、Arel #matchesはSQLインジェクション攻撃の影響を受けないようです。

2
bfcoder