[patch] ActiveResource doesn't support file uploads/attachments #831

Closed
lighthouse-import opened this Issue May 16, 2011 · 8 comments

8 participants

@lighthouse-import

Imported from Lighthouse. Original ticket at: http://rails.lighthouseapp.com/projects/8994/tickets/6392
Created by Nick M - 2011-02-09 05:26:58 UTC

Problem

ActiveResource doesn't currently support file objects within an instance. If you try and save an ActiveResource instance that contains a file attachment, the file object's attributes get serialized, but not the file itself. For example, this is what ActiveResource currently sends when trying to create a new object that contains an uploaded file:

    <user>
      <first-name>Tom</first-name>
      <last-name>Jones</last-name>
      <address>1234 Test Rd</address>
      <avatar type="yaml">--- !ruby/object:ActionDispatch::Http::UploadedFile 
    content_type: image/png
    headers: |
      Content-Disposition: form-data; name="user[avatar]"; filename="Picture 4.png"
      Content-Type: image/png

    original_filename: Picture 4.png
    tempfile: !ruby/object:File {}
    </avatar>
    </user>

That serialized <avatar> content obviously won't work on the remote server since it doesn't actually contain the file data. You can try to base64 encode your file content inside the XML or JSON data being sent to the remote server, but that is cumbersome, slow, and requires individual changes to both your client and server code.

Patch

I've attached a patch with tests (for both master and the 3-0-stable branch) that gives you the option to send and encode your ActiveResource POST and PUT request data as application/x-www-form-urlencoded or, when file attachments are present, multipart/form-data. Since Net::HTTP doesn't natively handle mutlipart attachments, I introduced a dependency on the Payload class from rest-client.

To enable this new encoding option, I added a new class attribute, ActiveRecord::Base.payload_encoding. It works similar to how the format option works (it can be set globally or on a per-class basis). payload_encoding defaults to :serialized for compatibility (data will continue to be posted as serialized JSON or XML). Or payload_encoding can be set to :form to encode the attributes as form elements/multipart data for attachments.

This feature also seems handy to have for remote web services that expect data encoded this way (and not as JSON or XML).

Finally, regarding compatibility, it's disabled by default so it shouldn't interfere, but if you're targeting a Rails-based backend service, I believe enabling it should be mostly seamless. Since a Rails backend will automatically decode the XML and JSON data sent to into form parameters anyway, this simply negates the need for that step.

Example

    class Image < ActiveResource::Base
      self.site = "http://localhost:3001/"
      self.format = :json
      self.payload_encoding = :form
    end

Image.find and others will continue to fetch the data using JSON. However, Image.create and other save methods will post the data as form attributes, allowing multipart attachments to also work.

@bradseefeld

Any reason this was closed without merging?

@kendagriff

I'm also curious if this will ever come to fruition.

@JohnColvin

+1 for a way to do this

@develop7

So, um, no further discussion here?

@marlonmantilla

+1 would be nice to have it, any idea why this was closed ?

@samiljin

+1

@rafaelfranca
Ruby on Rails member

Active resource was extracted from rails

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment