Получить путь к файлу ActiveStorage на диске

Мне нужно получить путь к файлу на диске, который использует ActiveStorage. Файл хранится локально.

Когда я использовал скрепку, я использовал метод path во вложении, который возвращал полный путь.

Пример:

user.avatar.path

Если посмотреть на документы Active Storage, похоже, что rails_blob_path. После просмотра того, что он возвратил, он не указывает путь к документу. Таким образом, он возвращает эту ошибку:

Нет такого файла или каталога @rb_sysopen -

Фон

Мне нужен путь к документу, потому что я использую гем comb_pdf для объединения нескольких PDF файлов в один PDF файл.

Для реализации скрепки я перебрал полные пути выбранных вложений PDF и load их в объединенный файл PDF:

attachment_paths.each {|att_path| report << CombinePDF.load(att_path)}

Ответы

Ответ 1

Благодаря помощи @muistooshort в комментариях, после просмотра кода Active Storage, это работает:

active_storage_disk_service = ActiveStorage::Service::DiskService.new(root: Rails.root.to_s + '/storage/')
active_storage_disk_service.send(:path_for, user.avatar.blob.key)
  # => returns full path to the document stored locally on disk

Это решение кажется мне немного странным. Я хотел бы услышать о других решениях. Это работает для меня, хотя.

Ответ 2

Просто используйте:

ActiveStorage::Blob.service.send(:path_for, user.avatar.key)

Вы можете сделать что-то подобное на вашей модели:

class User < ApplicationRecord
  has_one_attached :avatar

  def avatar_on_disk
    ActiveStorage::Blob.service.send(:path_for, avatar.key)
  end
end

Ответ 3

Я не уверен, почему все другие ответы используют send(:url_for, key). Я использую Rails 5.2.2, а url_for является публичным методом, поэтому лучше избегать send или просто вызывать path_for:

class User < ApplicationRecord
  has_one_attached :avatar

  def avatar_path
    ActiveStorage::Blob.service.path_for(avatar.key)
  end
end

Стоит отметить, что в представлении вы можете делать такие вещи:

<p>
  <%= image_tag url_for(@user.avatar) %>
  <br>
  <%= link_to 'View', polymorphic_url(@user.avatar) %>
  <br>
  Stored at <%= @user.image_path %>
  <br>
  <%= link_to 'Download', rails_blob_path(@user.avatar, disposition: :attachment) %>
  <br>
  <%= f.file_field :avatar %>
</p>

Ответ 4

Вы можете загрузить приложение в локальный каталог, а затем обработать его.

Предположим, что у вас есть в вашей модели:

has_one_attached :pdf_attachment

Вы можете определить:

def process_attachment      
   # Download the attached file in temp dir
   pdf_attachment_path = "#{Dir.tmpdir}/#{pdf_attachment.filename}"
   File.open(pdf_attachment_path, 'wb') do |file|
       file.write(pdf_attachment.download)
   end   

   # process the downloaded file
   # ...
end