Rails 7.1.3中如何用Ransack搜索ActiveStorage附件文件名?
解决方案
问题根源
has_one_attached :file 并未在Upload模型上直接创建名为file的Active Record关联,而是生成了两个底层关联:file_attachment(对应ActiveStorage::Attachment)和file_blob(对应ActiveStorage::Blob)。文件名存储在Blob的filename字段中,必须通过这两层关联构建搜索条件。
步骤1:修正Upload模型的可搜索配置
修改upload.rb,指定正确的可搜索关联,并声明可访问的嵌套字段:
class Upload < ApplicationRecord has_one_attached :file def self.ransackable_associations(auth_object = nil) ["file_attachment"] end def self.ransackable_attributes(auth_object = nil) super + ["file_attachment_blob_filename"] end end
步骤2:让ActiveStorage::Blob支持Ransack
在config/initializers/active_storage_ransack.rb(无则新建)中添加Blob的可搜索属性配置:
class ActiveStorage::Blob < ApplicationRecord def self.ransackable_attributes(auth_object = nil) ["filename", "content_type", "created_at", "id"] end end
步骤3:修正视图搜索字段
将搜索字段改为指向Blob的文件名字段:
<%= f.search_field :file_attachment_blob_filename_cont, autofocus: true, placeholder: "Search by filename" %>
步骤4:优化控制器查询关联
修改控制器代码,提前加载关联避免N+1查询:
@q = Upload.ransack(params[:q]) @uploads = @q.result.includes(file_attachment: :blob)
可选:自定义Ransacker简化字段名
如果觉得嵌套字段名过长,可在Upload模型中添加自定义ransacker,简化视图调用:
class Upload < ApplicationRecord has_one_attached :file # ... 保留其他配置代码 ... ransacker :filename do Arel.sql("active_storage_blobs.filename") end def self.ransackable_attributes(auth_object = nil) super + ["filename"] end
之后视图可直接使用简化字段:
<%= f.search_field :filename_cont, autofocus: true, placeholder: "Search by filename" %>
内容的提问来源于stack exchange,提问作者hashrocket
相关产品推荐
相关产品推荐

