I am fairly new to Rails and have been making steady progress on a Mobile Web App I am working on for our local high school but have run into an issue which I am stumped on. I am hoping the collective knowledge here will point me in the right direction.
I have a model for the school athletes (first name, last name, height, weight, graduation years, - standard stuff) which is working (CRUD via standard scaffold generation) and now I want to add the ability to import records via CSV upload.
In an effort to not reinvent the wheel, I am following this example from Rich on Rails. To get familiar with it, I created a separate Rail project and followed the example and it all works as expected. Great. Now to integrate into my existing project.
Everything seems to integrate fine with one exception - the CSV file is never passed to my model in the params I cannot figure out why. I am sure it is something obvious but I have stared at this problem for several hours and am unable to see what I am doing wrong.
Here is a portion of my Athletes controller:
class AthletesController < ApplicationController
before_action :set_athlete, only: [:show, :edit, :update, :destroy]
# GET /athletes
# GET /athletes.json
def index
@athletes = Athlete.all.order(:lastname, :firstname)
end
# POST /athletes/import
# POST /athletes/import.json
def import
logger.info(params.to_yaml)
begin
Athlete.import(params[:file])
redirect_to page_path('admin'), notice: "Athletes imported."
rescue
redirect_to page_path('admin'), notice: "Invalid CSV file format."
end
end
# GET /athletes/1
# GET /athletes/1.json
def show
end
# GET /athletes/new
def new
@athlete = Athlete.new
end
# GET /athletes/1/edit
def edit
end
My model looks like this:
class Athlete < ActiveRecord::Base
# an athlete can be on more than one team
has_and_belongs_to_many :teams, through: :athletes
require 'csv'
## CSV import
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
athlete_hash = row.to_hash # exclude the ? field
athlete = Athlete.where(id: athlete_hash["id"])
if athlete.count == 1
athlete.first.update_attributes
else
Athlete.create!(athlete_hash)
end # end if !athlete.nil?
end # end CSV.foreach
end # end self.import(file)
I've added this onto my index view for testing, later on it will be in an admin area:
<div>
<h3>Import a CSV File</h3>
<%= form_tag import_athletes_path, multipart: true do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
No matter what I do, I never get the value of the file_field_tag to come through to the controller. If I add other fields using text_field_tag they come through as expected but the file_field_tag value never does.
--- !ruby/hash:ActionController::Parameters
utf8: "✓"
authenticity_token: it3yBxBnzA4UQ/NILP5GNoYJeO5dyg+Z+VfhE/C6p7k=
commit: Import CSV
action: import
controller: athletes
Redirected to http://localhost:3000/
Completed 302 Found in 8ms (ActiveRecord: 0.0ms)
I am stumped - if anyone has any ideas as to what I might be doing wrong, I would be grateful. I have about 300 athletes which I want to import and have no desire to type them in.
It turns out because I am using jQuery Mobile for my framework, I need to add "data-ajax=false" to my form tag. This change to my form allowed the file parameter to be visible in the controller:
<h3>Import a CSV File</h3>
<%= form_tag(import_athletes_path, { :multipart => true, :'data-ajax' => false }) do %>
<%= file_field_tag :file %>
<%= submit_tag "Import CSV" %>
<% end %>
</div>
A short while ago I recalled reading something about file uploads and jQuery Mobile not working by default. It is due to the standard AJAX navigation employed by jQM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With