# Image uploads in Rails

**URL:** <https://www.ruby-forum.com/t/image-uploads-in-rails/75199>\
**Category:** Rails\
**Created:** [November 8, 2006, 6:42am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199 "2006-11-08T06:42:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 6:42am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/1 "2006-11-08T06:42:05Z")

</div>

Hey guys! Things are going great for me - thanks in no small part to all  
the help i received here. I finished my site, and I’ll put up the url if  
people want to check it out.  
But that’s not the reason I’m posting today. I’m working on my next  
site, and I realized that I’m going to need to add image upload  
functionality to this one. My Ruby skills are minimal at this point, so  
I’m trying to find the most painless way to do this; i tried the  
file\_column plugin, but it doesn’t seem to do what it says it will do:  
it generates the html code for the upload ok but seems to stop there,  
and offers few clues how to write a controller method for it to link to;  
also the way the image is stored seems odd. I looked up the file upload  
how-to on the Rails site, but it seems very bare-bones as well.

Does anybody have a favorite method for this?

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 6:57am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/2 "2006-11-08T06:57:51Z")

</div>

Hey Sean,

you might want to check out the Flex Image plugin available at:

> **[Beautiful Pixel](https://beautifulpixel.com/)**
>
> A log of random code experiments and semi-useless thoughts from some software developer named Alex...

The plugin is an absolultely fantastic and I’m sure you’ll get a grip  
on it very fast. I find FlexImage to be way more easier to use than  
file\_column. So give it a try.

Cheers,  
Mike.

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 7:41am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/3 "2006-11-08T07:41:36Z")

</div>

Thanks man. I checked it out and it looks tight. Just have to install  
“RMagick”, which looks like a headache and a half. Looks like it will  
have to wait for tomorrow when I can find my XCode tools CD.

Just out of curiosity, are there any reliable methods out there that  
don’t require RMagick?

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 7:51am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/4 "2006-11-08T07:51:56Z")

</div>

I’d recommend using MacPorts for ruby and rb\_rmagick installations. It  
simply works.

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 9:23am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/5 "2006-11-08T09:23:59Z")

</div>

MacD wrote:

> Hey Sean,
> 
> you might want to check out the Flex Image plugin available at:  
> [http://beautifulpixel.com/](http://beautifulpixel.com/)  
> The plugin is an absolultely fantastic and I’m sure you’ll get a grip  
> on it very fast. I find FlexImage to be way more easier to use than  
> file\_column. So give it a try.
> 
> Cheers,  
> Mike.

Thank you, Mike!

Although, if you don’t need to resize or process the image in any way,  
then you don’t need FlexImage, and dont need RMagick.

The way the plugin handles uploads, however, could be easily reused.  
The basic idea is to override the property setter for the binary data on  
your model. Then the model handles writing it to the file system or  
database.

#model  
def image=(file)  
File.open(“#{RAILS\_ROOT}/public/images/#{file.original\_filename}”,  
“w+”) do |f|  
f.write file.read  
end  
end

#view  
\<%= form\_tag({:action =\> ‘upload’}, {:multipart =\> true}) %\>  
\<%= file\_field ‘avatar’, ‘image’ %\>  
\<%= submit\_tag ‘Upload image!’  
\<%= end\_form\_tag %\>

#controller  
def upload  
Avatar.create(params[:avatar])  
end

But if you want to do any kind of processing or vlaidation on that  
image, you need to install rmagick. RMagick is the only ruby library  
out there that can read, process and write images.

And if you need to display images at different sizes or ensure uploads  
do not exceed a certain image size, then FlexImage will make your life a  
whole lot easier.

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 9:47am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/6 "2006-11-08T09:47:19Z")

</div>

Wow. That’s very little code.  
I love Rails.

Anyway, I know this is the kind of question that probably everybody  
hates, but if anyone has the patience, could you break down a few points  
in this technique for the non-programmer?

For example, this notation:

> def image=(file)

I’d understand “def image(file)”, where image would be the function name  
and file would be the parameter, but I’ve never seen an equals sign used  
that way before. What does it do?

and this:

> ```
> File.open("#{RAILS_ROOT}/public/images/#{file.original_filename}", 
> 
> ```
> 
> “w+”) do |f|  
> f.write file.read

is “original\_filename” real code or pseudocode?

this i get:

> \<%= form\_tag({:action =\> ‘upload’}, {:multipart =\> true}) %\>  
> \<%= file\_field ‘avatar’, ‘image’ %\>  
> \<%= submit\_tag ‘Upload image!’  
> \<%= end\_form\_tag %\>

But this:

> def upload  
> Avatar.create(params[:avatar])  
> end

this means that I would need an “Avatar” model, right? And the file  
would just be stored in the images folder and no database activity would  
take place?

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 8, 2006, 6:56pm UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/7 "2006-11-08T18:56:21Z")

</div>

Sean C. wrote:

> Wow. That’s very little code.  
> I love Rails.

Absolutely

> Anyway, I know this is the kind of question that probably everybody  
> hates, but if anyone has the patience, could you break down a few points  
> in this technique for the non-programmer?
> 
> For example, this notation:
> 
> > def image=(file)
> 
> I’d understand “def image(file)”, where image would be the function name  
> and file would be the parameter, but I’ve never seen an equals sign used  
> that way before. What does it do?

adding an equals sign just makes an equal sign part of the method name.  
You can also have ? and ! in your method names. What this does is when  
you say:

SomeModel.image = params[:some\_model][:image]

It will call the image= method with the argument of  
params[:some\_model][:image]. Ruby does not interpret the above code as  
an assignment, but rather simply a method call. The reason this works  
with:

SomeModel.create(params[:some\_model])

Is that rails internally takes every attribute the hash that you provide  
to the create method and calls the “=” method for it. So when you  
write:

SomeModel.create({:foo =\> ‘bar’, :baz =\> ‘123’})

Rails internally executes:

model = SomeModel.new  
model.foo = ‘bar’  
model.baz = ‘123’  
model.save

So when we define an “attribute=(value)” method it allows to wrap some  
other processing around a simple assignment, such as saving an uploaded  
image to the disk.

And as a minor note this magic also works with [] and []=

class Foo  
def   
“Passed in #{key.to\_s.upcase}”  
end  
def []=(key, value)  
“You tried to make the key #{key} the value of #{value}”  
end  
end

foo = Foo.new  
foo[:doodle] #=\> “Passed in Doodle”  
foo[:gnarf] = ‘foo’ #=\> “You tried to make the key gnarf the value of  
foo”

> and this:
> 
> > ```
> > File.open("#{RAILS_ROOT}/public/images/#{file.original_filename}", 
> > 
> > ```
> > 
> > “w+”) do |f|  
> > f.write file.read
> 
> is “original\_filename” real code or pseudocode?

Totally real code. Look in to “Multipart Requests” section of the CGI  
class documentation here: [http://www.ruby-doc.org/core/classes/CGI.html](http://www.ruby-doc.org/core/classes/CGI.html)

Uploaded files have a few extra methods, namely: orginal\_filename,  
local\_path, and content\_type

Although, you only need to use that if you care about the original  
filename. If you are mapping them directly to a model you may want to  
simply name the file with the id of the record it belongs to instead.

> But this:
> 
> > def upload  
> > Avatar.create(params[:avatar])  
> > end
> 
> this means that I would need an “Avatar” model, right? And the file  
> would just be stored in the images folder and no database activity would  
> take place?

Yes.

Or if you want it to write to a binary database field:

def image=(file)  
self[:image] = file.read  
end

the [] notation allows to read and write the attributes of your model if  
you have ovveridden the normal accessor methods like we did here. And  
the read method simply pulls all the data out of the file object as a  
string, a big string.

However, this entire methodology was assuming you wanted to store an  
image that directly relates to a record. If you just want to upload  
random images to a folder in your web root, meaning without any model at  
all, then its super easy.

Create a new file and write into it what you read out of the uploaded  
file. This is a snippet from one of my apps:

#view  
\<%= file\_field\_tag ‘file’ %\>

#controller  
def upload  
File.open  
“#{RAILS\_ROOT}/public/misc/#{params[:file].original\_filename}”, ‘wb’ do  
|f|  
f.write(params[:file].read)  
end  
redirect\_to :action =\> ‘index’  
end

---

<div class="post-metadata">

**Author:** ![smc7000](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ed655f/32.png) [@smc7000](https://www.ruby-forum.com/u/smc7000)\
**Post date:** [November 9, 2006, 1:44am UTC](https://www.ruby-forum.com/t/image-uploads-in-rails/75199/8 "2006-11-09T01:44:38Z")

</div>

Wow. Thanks for the breakdown, Alex. You’re still a bit ahead of me, but  
I can understand something like 70% of what you’re talking about. I’ll  
look up the rest. For now, what I want to do is just overwrite the same  
file, over and over. I’ve got, let’s say, a main graphic on my front  
page. I don’t need to keep records of what previous versions of that  
graphic were, so if I want to change the picture on my front page, all I  
have to do is overwrite the image file with a new on of the same name  
and refresh the browser.

For now, all I want to do is be able to change that image, over the web,  
without using FTP. Later, once I get a handle on that basic idea, I will  
be trying to implement more complicated functions, like associating  
uploaded images with a blog entry, renaming them to a standardized  
naming format using timestamps or something to keep them from  
overwriting each other, and (hopefully) checking and resizing them upon  
upload. But I know it will be some time and no small amount of studying  
before I get there.

Anyway, thanks!

sean
