1

I am trying to upload a csv file to Rails and parse it into a db. I have tried using both Paw and Postman to send the http request, specifying POST, attaching the csv file, and specifying Content-Type as application/csv

The request header:

POST /skate_parks/import HTTP/1.1
Content-Type: text/csv
Host: localhost:3000
Connection: close
User-Agent: Paw/2.3.4 (Macintosh; OS X/10.11.5) GCDHTTPRequest
Content-Length: 11663

Name,Address,Suburb,Postcode,State,Business Category,LGA,Region,
Aireys Inlet Skate Park,Great Ocean Road,Aireys Inlet,3231,VIC,Skate Parks,Surf Coast,Barwon S/W, etc...

The controller skate_parks_controller.rb

def import
  SkatePark.import(params[:body])
end

The model

class SkatePark < ApplicationRecord

  require 'csv'

  def self.import(file)
    CSV.foreach("file", headers: true) do |row|

      skate_park_hash = row.to_hash
      skate_park = SkatePark.where(name: skate_park_hash["name"])

      if skate_park.count == 1
        skate_park.first.update_attributes(skate_park_hash)
      else
        SkatePark.create!(skate_park_hash)
      end
    end
  end
end

The error

Started POST "/skate_parks/import" for ::1 at 2016-05-26 13:48:34 +1000
Processing by SkateParksController#import as HTML
Completed 500 Internal Server Error in 3ms (ActiveRecord: 0.0ms)
Errno::ENOENT (No such file or directory @ rb_sysopen - file):
app/models/skate_park.rb:6:in `import'
app/controllers/skate_parks_controller.rb:7:in `import'
alex
  • 5,467
  • 4
  • 33
  • 43
  • Uploading a csv is the same as any other file type. With that in mind it might be easier to find your answer – Tom Prats May 26 '16 at 04:36

1 Answers1

4

The problem is params[:body] is nil, so you're essentially calling SkatePark.import(nil). Rails doesn't put the raw POST body into params like you've apparently assumed it does.

You have two options. The better option, in my opinion, is to upload the data as multipart/form-data. Rather than putting the raw data into the POST body, you'll do the same thing a browser does when a user chooses a file in an <input type="file">, which is to say you'll encode it as form data. When you do that, you will be able to access the data through params, as described in the Form Helpers Rails Guide under "Uploading Files." (Since you apparently aren't using a form, you can skip to "What Gets Uploaded" to see how to handle the data you receive.)

To test this with Postman, follow the instructions for "form-data" under "Request body" in the Sending Requests docs, which I'll excerpt here for posterity:

multipart/form-data is the default encoding a web form uses to transfer data. This simulates filling a form on a website, and submitting it. The form-data editor lets you set key/value pairs (using the key-value editor) for your data. You can attach files to a key as well.

Your other option is to access the POST body directly via request.raw_post as described here: How to access the raw unaltered http POST data in Rails? This is not very "Railsy," however, and among other things will be harder to test.

Community
  • 1
  • 1
Jordan Running
  • 102,619
  • 17
  • 182
  • 182