Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to upload a file temporarily in Rails 3?

I'm creating CSV-upload functionality for a site of mine. I'm looking to upload a file, parse it, and then dispose of it.

I know I can upload and save a file using Paperclip, but that seems a bit like overkill.

All I need to do is parse the uploaded file and never save it. How would I go about doing this in Rails 3?

Note: I'd prefer to do the uploading manually without using an external gem so I can learn how to process works, but any suggestions are welcome.

Thanks!

like image 838
Yuval Karmi Avatar asked Dec 01 '11 23:12

Yuval Karmi


People also ask

How do you create a temp file in Ruby?

In any case, all arguments ( basename , tmpdir , mode , and **options ) will be treated as ::new. Creates a temporary file with permissions 0600 (= only readable and writable by the owner) and opens it with mode “w+”. The temporary file will be placed in the directory as specified by the tmpdir parameter.

What is activestorage?

1 What is Active Storage? Active Storage facilitates uploading files to a cloud storage service like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage and attaching those files to Active Record objects.


3 Answers

Use the file_field helper in your form, then in your controller you can use File.Write and File.read to save the file.

E.g. View

<%= form_for @ticket do |f| %>
  <%= f.file_field :uploaded_file %>
<% end %>

Controller

def upload
  uploaded = params[:ticket][:uploaded_file]
  File.open(<insert_filename_here>, 'w') do |file|
    file.write(uploaded.read)
  end
end

Edit: Just saw @klochner's comment, that link says pretty much what I have said so follow that: RubyOnRails Guides: Uploading Files.

like image 123
dnatoli Avatar answered Sep 21 '22 17:09

dnatoli


Paste this in your model

  def parse_file
   File.open(uploaded/file/path, 'w') do |f|  # Feed path that user gives in some way
   ## Parse here
   end
  end

this in view

  <%=form_for @page, :multipart => true do |f|%>

    <ul><li><%= f.label :file%></li>
    <li><%= f.file_field :uploaded_file%></li></ul>

  <%end%>

Let me know if this works. If it fails figure out a way to feed path of uploaded_file in parse_file method (the definite way which will work is storing file location in db and picking up from there, but it is not the right way to do this thing). Otherwise, I guess it should work.

like image 21
Bhushan Lodha Avatar answered Sep 18 '22 17:09

Bhushan Lodha


Complete Example

Take, for example, uploading an import file containing contacts. You don't need to store this import file, just process it and discard it.

Routes

routes.rb

resources :contacts do 
  collection do
    get 'import/new', to: :new_import  # import_new_contacts_path

    post :import, on: :collection      # import_contacts_path
  end
end

Form

views/contacts/new_import.html.erb

<%= form_for @contacts, url: import_contacts_path, html: { multipart: true } do |f| %>

  <%= f.file_field :import_file %>

<% end %>

Controller

controllers/contacts_controller.rb

def new_import
end

def import
  begin
    Contact.import( params[:contacts][:import_file] ) 

    flash[:success] = "<strong>Contacts Imported!</strong>"

    redirect_to contacts_path

  rescue => exception 
    flash[:error] = "There was a problem importing that contacts file.<br>
      <strong>#{exception.message}</strong><br>"

    redirect_to import_new_contacts_path
  end
end

Contact Model

models/contact.rb

def import import_file 
  File.foreach( import_file.path ).with_index do |line, index| 

    # Process each line.

    # For any errors just raise an error with a message like this: 
    #   raise "There is a duplicate in row #{index + 1}."
    # And your controller will redirect the user and show a flash message.

  end
end
like image 32
Joshua Pinter Avatar answered Sep 22 '22 17:09

Joshua Pinter