Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

Rails RMagick, image upload not in the model (See related posts)

Sometimes you don't want image upload in the model. Here's a controller class I use to upload a recipe image, standardize the size, create a thumbnail, and write them out.

This code uses a "attr_accessor :file" in the recipe model. file is not a table field, it's just a temporary variable for storing the data, before I load it into RMagick.
def do_upload_image
	 image_types = ["image/jpeg", "image/pjpeg", "image/gif", "image/png", "image/x-png"]
	 
	 @recipe = Recipe.find(params[:id])
	 @recipe.update_attributes(params[:recipe])
	 logger.info "@recipe.file = " + @recipe.file.to_s
	 if !@recipe.file.blank?
		 if (@recipe.file.size != 0) 
			 logger.info "content_type = " + @recipe.file.content_type.to_s
			 logger.info "size = " + @recipe.file.size.to_s
			 if (image_types.include?@recipe.file.content_type.chomp)
			 
				 if @recipe.file.size < 2097152
					 @recipe.file.rewind
					 
                                         # Load the file field directly into the blob, straight from memory and into RMagick!  No need to write the raw file out to the filesystem
					 pic = Magick::Image.from_blob(@recipe.file.read)[0]

                                         # I want to place the image inside a 200x200 jpg, with a white background. 
                                         # so all my images are the same size, while maintaning proportions.
					 width = pic.columns
					 height = pic.rows
					 if (width > height)
						 pic.scale!((200.0/width.to_f))
					 else
						 pic.scale!((200.0/height.to_f))
					 end
					 
					 back = Magick::Image.new(200,200) {
						 self.background_color = 'white'
						 self.format = 'JPG'
					 }
					 back.composite!(pic, Magick::CenterGravity, Magick::InCompositeOp)
					 
                                         # Now scale this down for a thumbnail
					 thumb = back.scale(50,50)
					 
					 # Add a rand to the filename, so if we upload a new image, we're shown it, instead of whatever we have cached.
					 rand = Kernel.rand(1000).to_s

					 File.open(RAILS_ROOT + "/public/images/recipes/" + @recipe.id.to_s + "-" + rand + ".jpg", "wb") do |f|
						 f.write(back.to_blob)
					 end
					 File.open(RAILS_ROOT + "/public/images/recipes/" + @recipe.id.to_s + "-" + rand + "t.jpg", "wb") do |f|
						 f.write(thumb.to_blob)
					 end

					 @recipe.picture = "/images/recipes/" + @recipe.id.to_s + "-" + rand + "." + "jpg"
					 @recipe.thumbnail = "/images/recipes/" + @recipe.id.to_s + "-" + rand + "t." + "jpg"
					 @recipe.file = nil
					 @recipe.save
					 
					 flash[:notice] = 'Image Uploaded and Thumbnailed'
					 redirect_to :action => "edit", :id => @recipe
					 #session[:recipe] = @recipe
				 else
					 flash.now[:error] = "File size greater then 2 Megabytes, please upload a smaller file."    
					 render :action => 'upload_image', :id => @recipe
				 end 
			 else 
				 flash.now[:error] = "File doesn't seem to be JPG, GIF, or PNG, please ensure it is a valid image file."    
				 render :action => 'upload_image', :id => @recipe
			 end
		 else
			 flash.now[:error] = "Unable to upload the file you selected, please try again."    
			 render :action => 'upload_image', :id => @recipe
		 end
	 else
		 flash.now[:error] = "Unable to upload the file you selected, please try again."    
		 render :action => 'upload_image', :id => @recipe
	 end
	 
 end

Comments on this post

cheapRoc posts on Oct 03, 2008 at 15:15
Holy Rails Controller Batman!

It must be nice to not have the guilt of breaking things into smaller components, loosely joined. I'd definitely not want to be the developer writing tests for this thing!
cheapRoc posts on Oct 03, 2008 at 15:15
NM: 2006, I guess you could get away with this sorta thing back then. :)

You need to create an account or log in to post comments to this site.