One of my project Lucas needs to enable users to upload pictures as their logos. How to get things done? In the book Agile Web Development with Rails, I’ve found a way.
All together, the code counts less than 50 lines.
Firstly we have to create a table to record the data. The columns should at least contain id, content-type and data, and the SQL maybe like follows:
OK. It’s time to start coding, and we have to create the model Logo and controller Logo.
In app/controllers/logo_controller.rb, there’re 3 actions. “get” will display a upload form, and “got” is the final page if upload succeeded, which show the picture by a tag. Of course, we use the “show” action to get data from the database and send to user.
Let’s start coding here:
app/models/logo.rb
The function “uploaded_logo” contains a little bit magic. Continue to see the upload form you’ll see why use this.
app/views/logo/get.rhtml
In the above template file, we created a upload field named “uploaded_logo”, so when the form is submitted, the function “uploaded_logo=” will be called . Of course, we need to edit the controller.
app/controllers/logo_controller.rb
Take a look at the “view” action, it makes good use of function “send_data”. Now we’re able to get the picture via /view/id , which contains extra content-type message in the header. Now it’s the last part of this demo, the template of action “got”.
app/views/logo/got.rhtml
Of course, to make the pages better, you have to create a layout for logo. Besides, you may need to do some verification before enabling the upload.
If you want to store the pictures in files, just read the data out and write to a new file, which is in a visitable folder.
All together, the code counts less than 50 lines.
Firstly we have to create a table to record the data. The columns should at least contain id, content-type and data, and the SQL maybe like follows:
CREATE TABLE IF NOT EXISTS `logos` (
`id` int(10) unsigned NOT NULL auto_increment,
`data` blob NOT NULL,
`content_type` varchar(30) collate utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT;
OK. It’s time to start coding, and we have to create the model Logo and controller Logo.
ruby script/generate model Logo
ruby script/generate controller Logo get got show
In app/controllers/logo_controller.rb, there’re 3 actions. “get” will display a upload form, and “got” is the final page if upload succeeded, which show the picture by a tag. Of course, we use the “show” action to get data from the database and send to user.
Let’s start coding here:
app/models/logo.rb
class Logo < ActiveRecord::Base
validates_format_of :content_type , :with => /^image/, :message => "你只能上传图片"
def uploaded_logo=(logo_field)
self.content_type = logo_field.content_type.chomp
self.data = logo_field.read
end
end
The function “uploaded_logo” contains a little bit magic. Continue to see the upload form you’ll see why use this.
app/views/logo/get.rhtml
<%= error_messages_for("logo") -%>
<% form_for (:logo, :url=>{:action => 'save'} , :html => {:multipart => true} ) do |form|%>
<%= form.file_field("uploaded_logo") %>
<%= submit_tag("Upload")%>
<%end%>
In the above template file, we created a upload field named “uploaded_logo”, so when the form is submitted, the function “uploaded_logo=” will be called . Of course, we need to edit the controller.
app/controllers/logo_controller.rb
class LogoController < ApplicationController
def get
@logo = Logo.new
end
def save
@logo = Logo.new(params[:logo])
if @logo.save
redirect_to(:action => "got" , :id => @logo.id)
else
render :action=>"get"
end
end
def view
@logo = Logo.find(params[:id])
send_data(@logo.data, :type=>@logo.content_type,:disposition=>"inline")
end
def got
@logo = Logo.find(params[:id])
end
end
Take a look at the “view” action, it makes good use of function “send_data”. Now we’re able to get the picture via /view/id , which contains extra content-type message in the header. Now it’s the last part of this demo, the template of action “got”.
app/views/logo/got.rhtml
<img src="<%= url_for :action=>"view", :id=>@logo.id %>" />
Of course, to make the pages better, you have to create a layout for logo. Besides, you may need to do some verification before enabling the upload.
If you want to store the pictures in files, just read the data out and write to a new file, which is in a visitable folder.