ruby-on-rails Carrierwave返回临时文件的路径,而不是回调中的实际路径

y53ybaqx  于 2023-02-20  发布在  Ruby
关注(0)|答案(2)|浏览(122)

在一个应用程序中,我想通过after_create回调函数将公共文件的URL发送到一个服务。因此,代码(简化后)如下所示:

class UserProfile < ApplicationRecord
  mount_uploader :video, VideoUploader
  after_create :send_url_to_service

  private

  # Just logs the URL
  def send_url_to_service
    Rails.logger.info video.url
  end
end

令我沮丧的是,在上传之后,send_url_to_service回调总是记录缓存的文件路径-类似于'uploads/tmp/1473900000-123-0001-0123/file.mp4'而不是'uploads/user_profiles/video/1/file.mp4'。我试图编写一个方法来从实际的文件路径形成URL,但它没有工作,因为文件还没有在那里。
因此,问题是,在这种情况下如何获得最终文件URL?
请注意,这是一个自我回答的问题,我只是想分享我的经验。

tf7tbtn2

tf7tbtn21#

我的解决方案是使用after_commit ..., on: :create回调函数而不是after_create

class UserProfile < ApplicationRecord
  mount_uploader :video, VideoUploader
  after_commit :send_url_to_service, on: :create

  private

  # Just logs the URL
  def send_url_to_service
    Rails.logger.info video.url
  end
end

答案是显而易见的,尽管我浪费了很长时间来绕着它打转。解释很简单:after_commit回调仅在所有信息成功持久化后触发。在我的例子中,文件尚未持久化到存储目录(在after_create阶段)-这就是为什么我得到了临时文件的URL而不是实际的URL。希望这对某些人有所帮助并节省他们的时间。

5jvtdoz2

5jvtdoz22#

使用Rails 7.0.4和carrierwave 2.0,使用after_commit :foo, on: :create回调仍然为我返回临时路径。
使用Carrierwave callbacks,特别是在uploader类本身中使用after :store, :foo,可以确保获取文件URL的调用只在文件上传到云存储之后发生。

# app/uploaders/video_uploader.rb

class VideoUploader < CarrierWave::Uploader::Base
  after :store, :foo

  def foo(_new_file)
    Rails.logger.info model.video.url
  end
end

注:

  • foo方法需要一个参数才能工作。在本例中,使用未使用的_new_file参数。
  • 变量model指向上载程序所连接到的示例对象。

相关问题