Ruby on Rails CSV upload&import - File name too long
Thanks to the input of the other answers I found the solution myself. The problem is that .read
turns the file into a string with the contents, but CSV.foreach()
expects a filename or path . Using .path
instead solves the problem:
if request.post? && params[:file].present?
inputPath = params[:file].path
CSV.foreach(inputPath) do |row|
#save row here
end
end
Rails 4 Error in CSV Import
You would get that error from calling CSV.open(file.path, nil, :ignore)
on any CSV, for example:
require 'csv'
# open a new CSV and write a couple of rows
CSV.open("test.csv", "w") do |csv|
csv.puts ["test", "header"]
csv.puts ["test", "data"]
end
# now try and open that same CSV with 2nd and 3rd args nil and :ignore
csv = CSV.open("test.csv", nil, :ignore)
# => TypeError: no implicit conversion of Symbol into Integer
CSV::open
is documented here (for Ruby 1.9.2). The second argument should be an open mode (e.g. read, write, append) - see a list on SO - and the third can be an options hash. Continuing the above, you might try something like the following:
csv = CSV.open("test.csv", "r")
csv.readline # note there is no CSV#row method
# => ["test", "header"]
csv.readline
# => ["test", "data"}
csv.close # if you're not passing a block to CSV::open, be sure to close the file
Note that there is also a CSV::read
method which can be more suitable for dealing with header rows in CSV files - have a read through the documentation to find out more.
Importing CSV's with different Column Headers each time in rails
Create a table for importing csv data to. Let's call it CsvDatum
. Fix columns that are shared by all your csv's and create a third text
column to store a hash containing the extra attributes. Let's say all csv's have name and email. You schema should be as follows.
create_table "csv_data", force: :cascade do |t|
t.string "name", limit: 255
t.string "email", limit: 255
t.text "extra_columns", limit: 65535
end
In your model
class CsvDatum < ActiveRecord::Base
serialize :extra_columns, Hash
end
Now when you are reading your csv file create an instance of the CsvDatum
class to hold row data.
CSV.foreach("path/to/file.csv", headers: true) do |row|
data = CsvDatum.new(name: row["name"], email: row["email"])
row.delete["name"]
row.delete["email"]
data.extra_columns = row.to_hash
data.save
end
How to best import and process very large csv files with rails
- to import csv faster, my suggestion is using gem smarter_csv, you can cek from their website tilo/smarter_csv
- as stated from their site: > smarter_csv is a Ruby Gem for smarter importing of CSV Files as Array(s) of Hashes, suitable for direct processing with Mongoid or ActiveRecord, and parallel processing with Resque or Sidekiq
- I use this gem and combined with resque
below is sample code to import file
n = SmarterCSV.process(params[:file].path) do |chunk|
Resque.enqueue(ImportDataMethod, chunk)
end
after it read file, passed the data record to resque and then import it in background (if you using rails 4.2 above you can combine with rails active job)
Problems importing a CSV that has a filename as a string in Rails
You can't use the image=
method; that's a CarrierWave method (overloading ActiveRecord's) which you're misusing when trying to set a string directly.
You can instead use write_attribute
product_image.raw_write_attribute(:image, row[2])
This internally is what ActiveRecord uses inside it's image=
method.
rails Import csv file, but saving blank
This line seems strange:
product.attributes = row.to_hash.slice(accepts_nested_attributes_for)
The class method accepts_nested_attributes_for
has a completely different purpose than listing the attribute names of Product
. But you could use attribute_names
. Try this:
product.attributes = row.to_hash.stringify_keys.slice(*attribute_names)
Note that stringify_keys
might be unnecessary, depending on how exactly the hash returned by row.to_hash
looks. Also note that slice takes a list of attribute names, not an array. The asterisk *
allows us to use the elements of an array as individual arguments to a function.
Ruby on Rails - Import Data from a CSV file
require 'csv'
csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
Moulding.create!(row.to_hash)
end
Related Topics
How to Use 'Debugger' and 'Pry' When Developing a Gem? (Ruby)
Cannot Install Ruby 1.9.3 on a Clean Lion Install
Devise 'Find_First_By_Auth_Conditions' Method Explanation
Setting a Text Field That Has a Jquery Mask on It
Unexpected =>, Expecting '}' in Rspec Expect
How to Create This File Input and Output Assignment in Ruby
Removing All Installed Gems and Starting Over
Get File Name and Extension in Ruby
Enter & Ioerror: Byte Oriented Read for Character Buffered Io
On Destroying Session via Devise "Couldn't Find User with 'Id'=Sign_Out"
Sorting of 2D Array by Its Amount of in the Inner Elements
How to Use Link_To with Ajax in Rails 3.2.1
How to Access Ruby Method Inside Module and Inside a Class from Another .Rb File
Convert This Xml Request to a Proper Savon Request