FlexImage - Must upload image?

I’ve got the flexImage plugin working with my RESTful app (thanks to
Alex W.). The problem is when I render the ‘create’ method WITHOUT
uploading an image, I get an invalid image error. My ‘new’ view has
fields for the other attributes in the table (same table where the
images are uploaded), and I would like to enter in those details and
create a new object without having to upload an image. The image is an
option or can be uploaded at a later time. I’ve looked in the FlexImage
model source code and I’ve found where the error occurs (starts on line
4).

def data=(file)
file_is_a_url = file =~ %r{^https?://}

  unless file.respond_to?(:read) || file_is_a_url
    raise InvalidImage, 'Uploaded file contains no binary data.  Be

sure that {:multipart => true} is set on your form.’
end

  if file.size > 0
    # Convert a string URL to a file object
    file = open(file) if file_is_a_url

    begin
      # Create RMagick Image object from uploaded file
      if file.path
        img = Magick::Image.read(file.path).first
      else
        img = Magick::Image.from_blob(file.read).first
      end

      # Ensure file RMagick object validity
      raise InvalidImage, 'from_blob method on file returned nil.

Invalid format.’ if img.nil?

      # Convert to a JPG
      img.format = 'JPG'

      # Set image quality and save result to record
      self.rmagick_image = img

      # Perform image pre-processing
      process! @@upload_options unless @@upload_options.empty?

    rescue
      # File was not an image, mark for adding validation error
      invalidate_image_field

    ensure
      GC.start
    end
  else
    invalidate_image_field
  end

  self[data_field]
end

def [](field_name, *args) #:nodoc:
  if field_name.to_sym == data_field.to_sym && @@file_store
    @data ||= rmagick_image.to_blob
  else
    super(field_name, *args)
  end
end

def []=(field_name, value, *args) #:nodoc:
  if field_name.to_sym == data_field.to_sym && @@file_store
    @data = value
  else
    super(field_name, value, *args)
  end
end

Anyone know how I would be able to create a new object without
necessarily uploading an image at the same time?

def data=(file)
file_is_a_url = file =~ %r{^https?://}

unless file.respond_to?(:read) || file_is_a_url
  raise InvalidImage, 'Uploaded file contains no binary data.  Be

sure that {:multipart => true} is set on your form.’
end
[snip]

Anyone know how I would be able to create a new object without
necessarily uploading an image at the same time?

Name your form field something other than ‘data’. I’m using flex_image
(outside of REST) and my form field is named “image_file”. My forms are
two part, first part is data, second part is the image file. In the
second part I simply do this:

   unless params['image_file'].original_filename.empty? then
     @photo.data = params['image_file']
   end

That works for me…

-philip

Justin Ko wrote:

Anyone know how I would be able to create a new object without
necessarily uploading an image at the same time?

Like any uploaded file in Rails, you need to check that there is
actually data there, by checking the the uploaded file has a size > 0.

def upload_image
params[:my_model].delete(:image) if params[:my_model][:image].size >
0
if params[:my_model][:image].size > 0
MyModel.create(params[:my_model])
end
end

Sadly, rails will populate the parameter from the file field with a file
object, whether something was uploaded or not.

Now that you bring it up, there really ought to be a more graceful way
to handle this. Perhaps by making the upload optional, and only have it
required with:

validates_presence_of :data

Sound like a good plan?

-Alex

Oops. That should probably be:

def upload_image
params[:my_model].delete(:image) if params[:my_model][:image].size >
0
MyModel.create(params[:my_model])
end

The problem is when I render the ‘create’ method WITHOUT
uploading an image, I get an invalid image error.

Ok, I just checked in an alteration to the plugin. To get the behavior
you want use:

class Foo < FlexImage::Model
self.require_image_data = false
end

class FooController < AC::B
def create
@user = User.create(params[:user])
end
end

This will simply leave the data field as nil, or not write a file to the
disk, if there is no uploaded file. This means you no longer have to
check if the file exists in the controller. Simply pass the entire
params hash that you want into Model.create or Model.new and
FlexImage::Model will ignore it if its empty and require_image_data is
false.

However this is only useful if you want to have records without images.
If you have a model where the reason for the model existing is the
image, like an Avatar of a ProductImage, then this would not be a good
choice. The image validation errors should be your friend in those
cases.

It works in my tests. Please test it in your app and let me know if it
has the intended behavior.

I’m always open to making this plugin better. Don’t hesitate to ask.

Thanks! It works exactly how I wanted.