Allow Cloudinary Active Storage service to reuse preloaded blobs via options (avoid extra DB queries)
还没有人认领这个 Issue。
评估
调研方向
先定位 CloudinaryService#url 和私有辅助方法 #find_blob_or_use_key,然后检查 #delete 和 #exist? 如何调用该辅助方法。重新使用通过 URL 选项提供的可选 blob,同时保留现有的 key 处理和 fallback 行为;保持删除操作不变,并验证在提供 blob 时 URL 路径会避免额外的 blob 查找。
由索引模型根据 Issue 内容生成。
描述
Feature request for Cloudinary Ruby SDK
Please enhance the Cloudinary Active Storage service so that it can reuse a preloaded ActiveStorage::Blob instead of always querying the database.
I’m specifically proposing:
- Threading an optional
:blobthrough theoptionshash into the internal helper#find_blob_or_use_key. - Updating
#find_blob_or_use_keyto accept an optionalblob:parameter and use it when present. - Focusing primarily on
#urlwhile leaving#deleteand#exist?unchanged for now.
This keeps public APIs backwards compatible and only adds an opt-in optimization path.
Explain your use case
In my Rails app, ActiveStorage::Blob records are often already loaded in memory via includes / preload/with_attached_*.
When I call blob.url, Rails ends up delegating to the configured service’s #url method and passes along an options hash. I’d like to be able to include the already-loaded blob in that options hash so the Cloudinary service doesn’t need to look it up again by key.
For my specific workload, this primarily matters for generating URLs (#url), where blobs are very frequently preloaded. For deletions, blobs are less likely to be preloaded, so I’m less concerned about optimizing #delete right now.
Describe the problem you’re trying to solve
Currently:
-
CloudinaryService#find_blob_or_use_keyis a private helper used internally by:#url#delete#exist?
-
These methods pass a key to
find_blob_or_use_key, which then always does a DB lookup (unless the argument is already anActiveStorage::BlobKey). -
When calling
blob.url, Rails goes throughservice.url(key, options), and the options hash is forwarded — but there is no support in the Cloudinary service for using something likeoptions[:blob]to skip the DB query.
As a result:
- Even if I already have the
ActiveStorage::Blobinstance, the Cloudinary service will still callActiveStorage::Blob.find_by(key: key). - This can create unnecessary queries and N+1 patterns in attachment-heavy views or background jobs.
- There’s no way to opt in to a “I already have the blob, please reuse it” behavior.
#delete is more problematic to change because Blob#delete only passes the key to the service and doesn’t pass an options hash at all. In my case, blobs are less likely to be preloaded at deletion time, so I’m okay with leaving #delete as-is initially.
Do you have a proposed solution?
Yes.
1. Pass blob through the options hash for #url
Because blob.url already forwards an options hash to the service, the most compatible way is to use that:
- Allow callers of
service.url(includingblob.url) to passblobviaoptions[:blob]. - Inside
CloudinaryService#url, extractblobfromoptionsand pass it tofind_blob_or_use_key.
Conceptual example:
def url(key, filename: nil, content_type: '', **options)
blob = options[:blob]
key = find_blob_or_use_key(key, blob:)
# existing logic using key...
end
2. Update find_blob_or_use_key to accept an optional blob: argument
Then, update the private helper so that it reuses a provided blob if present, and falls back to the current behavior otherwise. For example:
def find_blob_or_use_key(key, blob: nil)
if key.is_a?(ActiveStorage::BlobKey)
key
else
begin
blob ||= ActiveStorage::Blob.find_by(key: key)
blob ? ActiveStorage::BlobKey.new(blob.attributes.as_json) : key
rescue ActiveRecord::StatementInvalid => e
# Return the original key if an error occurs
key
end
end
end
Why this is backwards compatible
-
Existing callers that do not pass a
:bloboption behave exactly as before:find_blob_or_use_keystill doesActiveStorage::Blob.find_by(key: key)and returns the same result type.- It still returns the key unchanged if it’s already an
ActiveStorage::BlobKey. - It still rescues
ActiveRecord::StatementInvalidand returns the original key.
-
The optimization is opt-in:
- Only when an upstream caller sets
options[:blob](for example,blob.url(blob: blob)or via a wrapper) will the Cloudinary service reuse the preloaded blob and skip the DB query.
- Only when an upstream caller sets
This enables applications that already manage preloaded blobs to avoid extra database queries when generating URLs (and, optionally, when checking existence), without breaking or changing the behavior for any existing users of the SDK.
- 主要语言
- Ruby
- 星标
- 420
- 派生
- 282
- PR 合并指标
- 30 天内没有已合并 PR
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
cloudinary/cloudinary_gem 的其他 Issue
-
难度 4/5 3-5 天 新手友好度 55/100
cloudinary/cloudinary_gem#597 · 1 条评论 ·
-
难度 2/5 1-3 小时 新手友好度 52/100
cloudinary/cloudinary_gem#591 · 3 条评论 ·
-
404's when fetching .eml files (from Action Mailbox)可能重新可做 @rnamba-cloudinary 于 400 天前认领,目前没有进行中的 PR。 未关闭
难度 4/5 3-5 天 新手友好度 30/100
cloudinary/cloudinary_gem#581 · 1 条评论 ·
-
BlobKey, MirrorService and Sidekiq 8 are incompatible可能重新可做 @const-cloudinary 于 541 天前认领,目前没有进行中的 PR。 未关闭
cloudinary/cloudinary_gem#573 · 3 条评论 · 已指派 1 人 ·
-
难度 4/5 3-5 天 新手友好度 30/100
cloudinary/cloudinary_gem#562 · 9 条评论 ·
查看 cloudinary/cloudinary_gem 的全部 Issue
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 65/100
维护者通常 1 天内回复
-
area: ci benchmark build developer-experience difficulty: easy dx enhancement github-actions good first issue hacktoberfest help wanted performance quality rank: 8 kyu ruby tech: ruby
难度 1/5 1 小时以内 新手友好度 82/100
flisk-sh/flisk-labs#22 ·
-
1.severity: security
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
15-minutes 5-minutes algorithm any-language beginner-friendly c cpp csharp easy go good first issue hacktoberfest help wanted java javascript kotlin python rust swift typescript
难度 1/5 1 小时以内 新手友好度 68/100
Huerte/algo-solutions-python#260 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复