NevD
NevD

Reputation: 315

Update attachment Rails Active Storage

I have a React frontend backed by a Rails API and I am sending photos to Cloudinary through Active Storage. My settings are standard: I have an Event model with the method has_one_attached :photo, and the POST endpoint '/api/v1/events' is served by the 'Events#create' method with simply @event = Event.new(event_params). I also save an additional column 'url' in the 'events' table in order to display it back whenever needed (and I get it with @event.photo.url (a warning says that 'service_url' is said to be depreciated). I can fetch it (browser's fetch api) and use it in React. That works.

When I edit my form and submit the form with a new photo, then I have to adapt the PATCH query with the following events#update method. I followed the Rails guides that says you should purge and create_and_upload!.

def update
    @event = Event.find(params[:id])
    logger.debug "..................BEFORE : ..#{@event.to_json}"
    if event_params[:photo] || @event.url
      @event.photo.purge
      @event.url = nil
    end    
    if @event.update(event_params)
      if event_params[:photo]
        ActiveStorage::Blob.create_and_upload!(
          io: File.open(event_params[:photo].tempfile),
          filename: event_params[:photo].original_filename,
          content_type:event_params[:photo].content_type
        )
        @event.url = @event.photo.url
      end
      logger.debug "................AFTER :.. #{@event.to_json}"
      render json: {status: :ok}
    else
      render json: {errors: @event.errors.full_messages},
        status: :unprocessable_entity, notice:"not authorized"
    end
end

My logs show that this produces an url but no url is sent to React. If I modify other fields in this form, I get the update back in React from Rails. However, the link isn't sent: url: null. I don't even use Active Job, but used 6.03 and even updated to 6.1. Anyone experienced this?

FI, the params hash contains the following:

"photo"=>#<ActionDispatch::Http::UploadedFile:0x00007fd938f1ecf8 @tempfile=#<Tempfile:/var/folders/11/whcyvzvx3w54zb0n1r0929200000gn/T/RackMultipart20200714-79173-t9s624.svg>, @original_filename="Rafting.svg", @content_type="image/svg+xml", @headers="Content-Disposition: form-data; name=\"event[photo]\"; filename=\"Rafting.svg\"\r\nContent-Type: image/svg+xml\r\n">}

Upvotes: 0

Views: 2641

Answers (1)

NevD
NevD

Reputation: 315

In case of any interest, I found an answer on how to update Active Storage. My model is Event with a column url that contains a Cloudinary link, and the attached active storage object is named photo). Then on a PATCH, firstly purge if needed and then just update the event.url column with the method .url (formerly .service_url) doing:

event.update(url: event.photo.url)

def update
    event = Event.find(params[:id])

    # purge if a link already exists and the params contain a new picture
    if event_params[:photo] && event.url
      event.photo.purge
    end

    if event.update(event_params)
      if event_params[:photo]
        event.update(url: event.photo.url)
      end
      render json: event, status: :ok
    else
      render json: {errors: event.errors.full_messages},
        status: :unprocessable_entity, notice:"not authorized"
    end
  end

The Rails guides seem misleading..

Upvotes: 1

Related Questions