2016-09-15 9 views
0

В приложении я хотел отправить общедоступный URL-адрес файла в службу в обратном вызове after_create. Таким образом, код (упрощенно) выглядел следующим образом:Carrierwave возвращает путь к файлу tmp вместо фактического в обратном вызове

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-адрес файла в такой ситуации?

P. S. Обратите внимание, что это вопрос, ответ на который я сам ответил, я просто хотел поделиться своим опытом.

ответ

2

Решение для меня было использовать 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 вместо фактического. Надеюсь, это помогает кому-то и экономит свое время.