У меня есть приложение Rails 7.1.3, в котором установлены ActiveStorage и Ransack. У меня есть модель под названием Upload вот эта has_one_attached :file. Я хотел бы выполнить поиск по имени файла, используя Ransack, в представлении uploads/index. Я попробовал ответы здесь и предложение здесь, но ни один из них не работает. Я также пытался создать lib/active_storage/attachment.rb и добавить rasackable_attributes, но все равно безуспешно. Я получаю ошибку Association named 'file' was not found on Upload; perhaps you misspelled it?. Кто-нибудь знает, как заставить это работать?
Вот мой код:
# upload.rb
has_one_attached :file
def self.ransackable_associations(auth_object = nil)
["file"]
end
# lib/active_storage/attachment.rb
class ActiveStorage::Attachment < ApplicationRecord
def self.ransackable_attributes(auth_object = nil)
["blob_id", "created_at", "id", "id_value", "name", "record_id", "record_type"]
end
end
/uploads/index.html.erb
<%= f.search_field :file_filename_cont, autofocus: true, placeholder: "Search by filename" %>
# controllers/uploads_controller.rb
@q = Upload.ransack(params[:q])
@uploads = @q.result.includes(:file)





has_one_attached :file создает ассоциации file_attachment и file_blob:
https://github.com/rails/rails/blob/v7.1.3.3/activestorage/lib/active_storage/attached/model.rb#L114-L115
вы можете использовать отражения для проверки ассоциаций:
>> Import.reflections.keys
=> ["file_attachment", "file_blob"]
ActiveStorage::Blob — здесь хранится фактическое имя файла:
>> ActiveStorage::Blob
=> ActiveStorage::Blob(id: integer, key: string, filename: string, content_type: string, metadata: text, service_name: string, byte_size: integer, checksum: string, created_at: datetime)
# ^^^^^^^^^^^^^^^^
Соберите все это вместе:
# config/initializers/active_storage.rb
ActiveSupport.on_load(:active_storage_blob) do
def self.ransackable_attributes(auth_object = nil)
%w[filename]
end
end
# app/models/import.rb
class Import < ApplicationRecord
has_one_attached :file
def self.ransackable_attributes(auth_object = nil)
[]
end
def self.ransackable_associations(auth_object = nil)
["file_blob"]
end
end
# app/controllers/imports_controller.rb
class ImportsController < ApplicationController
# GET /imports
def index
@q = Import.ransack(params[:q])
@imports = @q.result
end
end
# app/views/imports/index.html.erb
<%= search_form_for @q do |f| %>
<%= f.label :file_blob_filename_cont %>
<%= f.search_field :file_blob_filename_cont %>
<% end %>
<%= render @imports %>
Кажется, работает:
>> Import.ransack({"file_blob_filename_cont"=>"ava"}).result
=> [#<Import:0x00007f9101d16048 id: 1>]
>> Import.ransack({"file_blob_filename_cont"=>"asdf"}).result
=> []
Мне пришлось добавить def self.ransackable_associations(auth_object = nil) %w[attachments] end в config/initializers/active_storage.rb, потому что я также искал другой атрибут Upload.