class Leave < ApplicationRecord
mount_uploaders :files, FileUploader
after_commit :do_something
private
def do_something
self.reload --- this is where it breaks. Works as expected w/o .reload
end
end
file_uploader.rb:
class FileUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_allowlist
%w[jpg jpeg gif png bmp doc docx txt pdf ppt pptx xls xlsx]
end
end
leaves_controller.rb:
module Api
module V1
class LeavesController < Api::V1::BaseJsonapiController
include Responsable
before_action :set_leave, only: %i[update_files destroy_files]
def update_files
save_params(Api::V1::LeaveResource) do
@leave.mute_notification = context[:user]&.admin? && @leave.employee != context[:user]
@leave.files += params[:files]
@leave.save!
end
end
end
end
routes.rb:
scope module: :api, defaults: { format: :json }, path: 'api' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
jsonapi_resources :leaves do
collection do
get :pending_count
end
member do
patch :files, action: :update_files
delete :files, action: :destroy_files
end
end
end
end
Just don't do that. CarrierWave 2.x stores attachments in the after_commit hook. It is obvious that mutating the object's state in after_commit breaks its functionality.
leave.rb:
file_uploader.rb:
leaves_controller.rb:
routes.rb:
Steps to reproduce:
PATCH request to /api/leaves/:id/files
Get the URL of the file
Leave.find(218).files.map(&:url)
=> 'https://host_name.s3.amazonaws.com/uploads/leave/photo/2/pic.png'Expected Result: Content of the uploaded file is returned
Actual Result: NoSuchKey is returned