ROR newb with MVC question

I’m new to ROR and still trying to wrap my mind around the MVC construct. Hope someone can spot what is probably a simple error here.

I need to have a user upload a CSV file, parse the header (the table field names) then each row of data, and import the data into its respective tables.

In the view I have:

<% form_tag ({:action => ‘uploadFile’}, :multipart => true) do %>

Select File : <%= file_field 'upload', 'datafile' %>

<%= submit_tag "Upload" %> <% end %>

in the controller:

class UploadController < ApplicationController

def index
render :file => ‘app\views\upload\uploadfile.html.erb’
end

def uploadFile

post = Import.proc_csv( params[:upload])
flash[:notice] = "File imported successfully"
redirect_to :action => :index

rescue

  flash[:error] = "Error importing file"
  redirect_to :action => 'index'

end

end

and in the model:

class Import < ActiveRecord::Base

require ‘fastercsv’

def self.proc_csv(upload)
row_count = 0
FasterCSV.foreach([:csv_import][:file], :headers => :first_row) do |row|

  @gr = Genotype_runs.create(:genotype_date_1=>row[4],:genotype_date_2=>row[5],:genotype_date_3=>row[6])
  # use the id of the Genotype_runs record to link to Genotype_data rec.
  Genotype_data.create(:genotype_run_id=> gr.id, :box=>row[0], :subjectid=>row[1], :labid=>row[2], :well=>row[4], :created_at=>Time.now,:updated_at=>Time.now)
  # print message showing import
  $stderr.print "\r%5d ..." % csv.lineno
  $stderr.flush
  row_count = row_count + 1
end  

end

def self.save(upload)
name = upload[‘datafile’].original_filename
directory = “public/data/import”
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, “wb”) { |f| f.write(upload[‘datafile’].read) }
end
end

The file upload screen allows me to upload a file, but when I submit it, I get the following error:

The most obvious answer is: do you have a file
app\views\upload\uploadfile.html.erb? (also, why the backslashes?)

Not quite sure why you're rendering a file like that...the idiomatic

way is to have a file in app/views/uploads/index.html.erb that
displays whatever you want (in this case presumably some form of the
CSV data). Rails assumes this and will render index.html.erb
without any explicit rendering.

Garrett Lancaster

compose-unknown-contact.jpg

Thanks for catching my dumb error with the backslashes…(this is running on Linux after all…). As you can tell, I’m crudely cutting-&-pasting code from online examples…

Yes, there is a file app/views/upload/uploadfile.html.erb, which is the view for my Upload class.

I’m not sure why I’m rendering the file like that either – it was just in an example I was trying to adapt to my purposes – but I do know if I take it out, the form doesn’t work anymore.
All I’m trying to do is have the Submit button feed the selected file to the controller correctly, and then to the model correctly, where the data gets imported into the database.
But I obviously still have major errors in how this is coded…

Any other suggestions appreciated…

Thanks again,
rixter

So, I commented out the index method in my controller, just leaving the view as before.

Now I get the error:

Unknown action

No action responded to index

so my question now is, why doesn’t the method uploadFile get called in the controller from the view with this code:

<% form_tag ({:action => ‘uploadFile’}, :multipart => true) do %>

Select File : <%= file_field 'upload', 'datafile' %>

<%= submit_tag "Upload" %> <% end %>

Still a mystery to me…

–rixter

It appears the uploadFile method is getting called because its
redirecting to :index, which doesn’t exist now since you deleted
it.

There are many issues here, but try the following:
1) put the code in uploadfile.html.erb in

app/views/upload/index.html.erb
2) uncomment the index action, but make it empty

Garrett Lancaster

compose-unknown-contact.jpg

OK, I must first inform you, I’m no rails guru (not yet anyways) but here is what I think should be your directory structure:

app/
controllers/
uploads_controller.rb # This will contain the UploadController class
views/
uploads/
index.html.erb # This will be the view to list the uploaded files (info)
new.html.erb # This will be the form used to upload files
models/
upload.rb # This is your model to represent an upload

Now that we have that in place, now the controller index method would automatically render the index.html.erb so there is no need for you to render the template directly. If you would like to see the list of uploaded document then may be you might need to the following your index controller method;

def index
@uploads = Upload.all # this gets all upload information and makes it available for the view
end

and then you render then in your view, i.e. the index.html.erb file do the following to list them all

    <%= @uploads.each do |upload| %>
  • <%= upload.title %>
  • <% end %>

So gives you list of upload info on the index.html.erb page. Now the next thing would be to actually create upload info; that where the new action (a controller method), and new.html.erb come in. A word of caution here; I have never done a form that uploads files so I can not give you much detail here, but there is a good gem called paperclip so you might want to check that out for details but here is what I would given the information you provided above.

In your controller you need to add the following action:

def new
@upload = Upload.new # This is a new upload model that you can use to create your upload form
end

then in you new.html.erb you add the following:

<% form_for(@upload) do |f| %>

Select File : <%= file_field 'upload', 'datafile' %>

<%= submit_tag "Upload" %> <% end %>

I kinda feel this is a bit incomplete but I’m sure someone can build on this or just find another way to help you with your problem. I hope this helped in making things clearer. If you are in need of a good place to start with RoR go here, railstutorial.org. I can say it is the best and most complete book I’ve ever read on programming. It’s that good!

Regards,
Tsega

Ok, I did the following:

  • moved the code to app/views/upload/index.html.erb
  • uncommented the index method in the controller, but made it empty
    Now, I no longer get any error message, but when I submit a file and click the Upload button, the form just flashes, but comes back with an empty field for the input file.
    So the desired method, uploadFile, is still not getting called in the controller.
    Here’s what the log says:
    Processing UploadController#index (for 127.0.0.1 at [blah,blah,blah]…
    Parameters: {“action”=>“index”, “controller”=>“upload”}
    Rendering upload/index
    I’m still puzzled: why is the uploadFile method not getting called, when the submit action clearly states:
    <% form_tag ({:action => 'uploadFile’}, :multipart => true) do %>

thx for the help,
still wondering,
rixter

Awesome…thanks Tsega…will chew on this awhile…a big help!

–rixter

One thing I forgot here is that you need to add the create action in your controller that would be used to house the code for uploading the file:

def create
post = Import.proc_csv( params[:upload])
flash[:notice] = “File imported successfully”
redirect_to :action => :index
rescue
flash[:error] = “Error importing file”
redirect_to :action => ‘index’
end

To test if the method is actually getting called place raise ‘Inside uploadFile’ at the top of the
method.

compose-unknown-contact.jpg