Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload File parameter not coming through to controller

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.

like image 925
Mike Walsh Avatar asked Sep 02 '14 14:09

Mike Walsh


1 Answers

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.

like image 66
Mike Walsh Avatar answered Oct 02 '22 21:10

Mike Walsh