Customers used to the Java & Oracle worlds are often scared by the Ruby on Rails switch. They want to be sure that this new tool will do at least as much as the old one. This is a perfectly understandable reaction.
To do so, they regularly ask for a POC (Proof of Concept) development to confirm that a given functionality can be easily implemented using Ruby on Rails.
During one on my last meetings, the following reflexion came to my ears : "Are you sure that it will be possible to upload files in our Oracle database? I tried myself another scripting language (PHP) and I encountered many issues with BLOB!".
So here is my POC responding to this question.
I specified Oracle in the title of this article but the following Ruby code has nothing specific to this database.
First of all, we need a table and a model to store data related to our file. You'll aslo need a controller and views.
You can use the scaffold script provided by Rails to generate this structure :
$ ./script/generate scaffold FileUpload name:string content_type:string content_size:integer content:binary
Here is my migration file :
class CreateFileUploads < ActiveRecord::Migration
def self.up
create_table :file_uploads do |t|
t.string :name
t.string :content_type
t.integer :content_size
t.binary :content
t.timestamps
end
end
def self.down
drop_table :file_uploads
end
end
Note the type of the content column : binary. This will generate a BLOB field in your database during the migration :
$ rake db:migrate
Nothing special about the model :
class FileUpload < ActiveRecord::Base
end
You can then modify the creation form (new.html.erb) :
<% form_for @file_upload, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :content %><br />
<%= f.file_field :content %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
The form has been defined has a multipart and the content field is now a file_field.
You can then work on the create method of your controller :
def create
@file_upload = FileUpload.new(params[:file_upload])
if @file_upload.valid?
@file_upload.name = params[:file_upload][:content].original_filename
@file_upload.content = params[:file_upload][:content].read
@file_upload.content_type = params[:file_upload][:content].content_type
@file_upload.content_size = params[:file_upload][:content].size
@file_upload.save
flash[:notice] = 'FileUpload was successfully created.'
redirect_to @file_upload
else
render :action => "new"
end
end
Nothing complicated here, the params[:file_upload][:content] holds an instance of ActionController::UploadedStringIO on which you can perform various operations as reading data, get content type and size, ... All this information is then stored in the database.
In the show.html.erb page, replace the content by a download link :
<p>
<b>Content:</b>
<%= link_to "Download", :action => "download", :id => @file_upload.id
%>
</p>
Finally, insert the download method in your controller and you're done!
def download
file = FileUpload.find(params[:id])
if file
send_data(file.content, :type => file.content_type , :filename => file.name)
else
flash[:error] = "Invalid file ID!"
redirect_to :action => "index"
end
end
One more time, it's very simple! The FileUpload record is extracted from the database using his ID. The associated file is then returned thanks to send_data method.
You can now save any kind of file in your Oracle database!
Add a comment
0 comment for this article