Project

General

Profile

Feature #859

Updated by Daniel Curtis over 7 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

Back