Feature #859
Updated by Daniel Curtis about 8 years ago
This is a simple guide for setting up a simple file upload to database with Ruby on Rails.
* Create the new Ruby on Rails web application:
<pre>
rails new uploadr
</pre>
* Change into the message_app directory:
<pre>
cd uploadr
</pre>
* Start the rails development web server locally:
<pre>
bundle exec rails s
</pre>
#* *NOTE*: The development web server bind the IP address to the localhost by default, so accessing it over the network will not work. To allow network access to the development web server:
<pre>
bundle exec rails s -b 0.0.0.0
</pre>
h2. Document Scaffold
* Generate the scaffold model, view, and controller code for the document.
<pre>
bundle exec rails generate scaffold document filename:string content_type:string file_contents:binary
</pre>
* Edit the route config:
<pre>
vi config/routes.rb
</pre>
#* And add the default route to the app:
<pre>
Uploadr::Application.routes.draw do
resources :documents
root :to => 'documents#index'
end
</pre>
* Edit the form view:
<pre>
vi app/view/documents/_form.html.erb
</pre>
#* And remove the unneeded *form div* tags, leaving the following:
<pre>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="actions">
<%= f.submit %>
</div>
</pre>
* Edit the document controller:
<pre>
vi app/controllers/documents_controller.rb
</pre>
#* And the following right b+efore the final end+ statement to allow *file* as a parameter so you can use it in the model:
<pre>
def document_params
params.require(:document).permit(:file)
end
</pre>
* Next edit the document model:
<pre>
vi app/models/document.rb
</pre>
#* And add the following to update the model to read and save the file
<pre>
def initialize(params = {})
file = params.delete(:file)
super
if file
self.filename = sanitize_filename(file.original_filename)
self.content_type = file.content_type
self.file_contents = file.read
end
end
private
def sanitize_filename(filename)
return File.basename(filename)
end
</pre>
h3. Showing the Document
* Edit the document controller again:
<pre>
vi app/controllers/documents_controller.rb
</pre>
#* And modify the show method to send the raw file for viewing:
<pre>
def show
send_data(@document.file_contents,
type: @document.content_type,
filename: @document.filename)
end
</pre>
h3. File Size Validation
* Edit the document model again:
<pre>
vi app/controllers/documents_controller.rb
</pre>
#* And modify the file using the following code:
<pre>
validate :max_file_size
def initialize(params = {})
# File is now an instance variable so it can be validated.
@file = params.delete(:file)
super
if @file
self.filename = sanitize_filename(@file.original_filename)
self.content_type = @file.content_type
self.file_contents = @file.read
end
end
NUM_BYTES = 1048576 # 1MB
def max_file_size
if (@file.size.to_f / NUM_BYTES) > 1
errors.add(:file, 'File size cannot be over #{NUM_BYTES} bytes.')
end
end
</pre>
h2. Resources
* http://ryan.endacott.me/2014/06/10/rails-file-upload.html
* https://matt.berther.io/2007/10/19/uploading-files-to-a-database-using-rails/
* https://www.tutorialspoint.com/ruby-on-rails/rails-file-uploading.htm
* https://gist.github.com/macek/610596