jaimerump
jaimerump

Reputation: 882

CarrierWave Add ActionDispatch::Http::UploadedFile After Model Processing

I have an Image model that requires me to have some data set up before I can save the image, because I determine where to upload the image to and what to name it depending on some data from the model. Right now I'm trying to do:

# ImagesController sets up data
img = Image.new
img.imageable = user
phashion_img = Phashion::Image.new(file.path)
img.image_hash = phashion_img.fingerprint.to_s
img.batch = img.latest_batch + 1
img.extension = 'jpg'
img.height = 640
img.width = 640

# ImageUploader uses it
version :original do
  def full_filename
    "#{model.image_hash}/orig/#{alnum_encode(model.imageable.id)}.#{model.extension}"
  end
end

I've run into an issue trying to pass the uploaded image into the uploader.

img.uploader.store! file gives me the error wrong number of arguments (1 for 0) img.uploader.store! file.tempfile gives me You are not allowed to upload "" files, allowed types: jpg, jpeg, gif, png

For reference, file is:

#<ActionDispatch::Http::UploadedFile:0x00000109ccdb70 @tempfile=#<Tempfile:/var/folders/lx/xk8vzr4s0fdd_m5w0syftfl80000gn/T/RackMultipart20140723-28731-1b5weu8>, @original_filename="20140522_164844.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"user[images_attributes][0][uploader]\"; filename=\"20140522_164844.jpg\"\r\nContent-Type: image/jpeg\r\n">

Which would make file.tempfile:

#<Tempfile:/var/folders/lx/xk8vzr4s0fdd_m5w0syftfl80000gn/T/RackMultipart20140723-28731-1b5weu8>

Is there any way I could pass either of these objects, ActionDispatch::Http::UploadedFile or Tempfile, to the Carrierwave uploader? Some transformation I can do to them so that the uploader can accept one of them?

Upvotes: 1

Views: 1518

Answers (1)

jaimerump
jaimerump

Reputation: 882

Since my use case is so far off from what is intended with CarrierWave, or any of the other image upload gems out there, I ended up rolling my own solution using the AWS-SDK gem to upload to S3. It's pretty specific, but I'm posting the gist of it on the off chance that it helps someone else.

# Image processing
magick = Magick::Image.from_blob( file.read )[0]

if !["JPG", "JPEG", "GIF", "PNG"].include? magick.format
  # Invalid format specified
end

orig = Image.new
orig.imageable = user
phashion_img = Phashion::Image.new(file.path)
orig.image_hash = phashion_img.fingerprint.to_s
orig.batch = orig.latest_batch + 1
orig.extension = magick.format.downcase
filename = "#{orig.image_hash}/orig/#{Alnum.encode(orig.imageable_id)}.#{orig.extension}"
orig.height = magick.rows
orig.width = magick.columns
orig.size = 'orig'

# Upload to S3
s3 = AWS::S3.new
uploaded_name = Rails.root.to_s+filename.gsub('/', '_')
magick.write( uploaded_name ) # Save file to filesystem so I can upload to S3
s3.buckets[bucket_name].objects[filename].write( open(uploaded_name), :acl => :public_read )
FileUtils.rm uploaded_name # Remove so it's not taking up space

# Crop
cropped = magick.crop(x.to_i, y.to_i, w.to_i, h.to_i, true) # Discard offset data to avoid borders

# Create Profile
# Resize_from is my own custom function to copy everything 
# but the size into another object and resize the image
resize_from(s3, orig, cropped, 640, 640)

# Create Grid
resize_from(s3, orig, cropped, 220, 220)

# Create Thumbnail
resize_from(s3, orig, cropped, 72, 72)

Upvotes: 0

Related Questions