2
votes

So I'm working on a rails 3.2 app where I have a CarrierWave uploader; which I use to upload images, and split crop them into a few different sizes - pretty standard stuff.

What I would like to do is composite a new image on top of the image being uploaded, which is also pretty straight forward. (very commonly done for watermarking). The difference is that instead of having static values for positioning the composited image, I need them to be dynamic.

The thing I'm having trouble with is figuring out how to pass dynamic user-defined positional arguments into my carrierwave processor in the 'version' block.

Any ideas?

4

4 Answers

13
votes

A little gotcha for rails 4: The other user options must be permitted in strong params before the file input param to properly be updated first and accessible via the Uploader.

4
votes

you can store the value into model instance

then, in the process method to get it by model attr

# model class
# define attr_accessor coords
class User < ActiveRecord::Base
  attr_accessor :coords
  mount_uploader :icon, AvatarUploader
end



# controller
# pass the params to @user.coords
def crop_icon
  @user.coords = params[:coords]
  @user.icon = params[:icon]
  @user.save
end



# Uploader
# the model in the function is same as @user in controll,
# and can be invoked inside of process method 
 def crop_area
    manipulate! do |img|
      unless model.coords.nil?
        coords = JSON.parse(model.coords)
        img.crop("#{coords['w']}x#{coords['h']}+#{coords['x']}+#{coords['y']}")
      end
      img = yield(img) if block_given?
      img
    end
  end
1
votes

I had similar issue. I called the Uploaders store method directly but it only accepts one parameter and that is file. I also needed to pass some id for storing the files in particular directory. This is what I ended up doing and was fairly simple:

I defined uploader instance variable as and a class method to set the value

class DocumentUploader < CarrierWave::Uploader::Base
    attr_accessor :cid

    def set_id id
        self.cid = id
    end
    ...
    def your_method
        my_id = self.cid
    end

end

Then in the controller action I did this:

uploader = DocumentUploader.new
uploader.set_id(id)
uploader.store!(my_file)
0
votes

Digging this out.

You can pass arguments like this

process do_stuff: ["foo", "bar"]

def do_stuff(arg_foo, arg_bar)
  arg_foo == "foo" # => true
  arg_bar == "bar" # => true
end

IMHO it's better than polluting model with dummy instance variables.