ActiveStorageを使用したモデルを考える
class User
has_one_attached :avatar
end
1人のユーザーがアバターを持っているかどうかを確認できます
@user.avatar.attached?
しかし、どのようにして、添付ファイルを持つすべてのユーザーのコレクションを返すことができますか?
joins
を使用して添付ファイルのあるすべてのユーザーを取得しようとしましたが、これはblobまたは添付ファイルテーブルのいずれでも機能しないようです。または、構文が正しくありません。
私は何か明白なものを見落としていると確信しています。次のように何かを行うことは可能ですか?
User.where(attached_avatar: nil)
もしそうなら、これはどこに文書化されていますか?
添付ファイルの関連付けは、次の規則に従って命名されます。
<NAME OF ATTACHMENT>_attachment
たとえば、has_one_attached :avatar
がある場合、関連付け名はavatar_attachment
になります。
添付ファイルの関連付けの名前がわかったので、他のアクティブレコードの関連付けと同じように、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")
レコードに添付ファイルがあるかどうかを知りたいので(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
少し関連していますが、添付されたレコードに対して検索クエリを実行する方法を次に示します。
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インジェクション攻撃の影響を受けないようです。