Comments for articles posted on https://pcreux.com.
pcreux / csv-importer Goto Github PK
View Code? Open in Web Editor NEWCSV Import for humans on Ruby / Ruby on Rails
License: MIT License
CSV Import for humans on Ruby / Ruby on Rails
License: MIT License
Comments for articles posted on https://pcreux.com.
Example:
ImportSubscriberCSV.new(model: newsletter.subscribers, file: file)
Thanks for the CSV importer. Maybe asking for too much but is there a demo site for this? :)
I use cscv-importer in conroller:
import = Importers::ImportMemberCSV.new(file: params[:import_file]) do
after_save { |member| list.subscribe(member) }
end
import.run!
Nonetheless I use after_save in block, it adds proc into Importers::ImportMemberCSV.config.after_save_blocks array
class Importers::ImportMemberCSV
include CSVImporter
model Member
column :email, to: ->(email) { email.downcase }, required: true
column :first_name
column :last_name
column :ip
when_invalid :skip
end
Hi,
I'm using an array of integers but csv-importer fails silently in this case. Here is an example sensor.csv with a name, date and an array of temperatures
sensor01,2017-01-28,14 17 19
Is there a way to specify that the last field is an array?
Edit: I know that I can reformat the csv file to something like
sensor01,2017-01-28,"{14, 17, 19}"
but maybe there's a clever way to do it in the class without modifing the csv file
All messages, such as The following columns are required:
should be put into locale files, so that could be replaced on the client side.
Current behavior is "skip".
We should wrap all imports in a transaction.
When selecting abort, we should call save!
skip_if do |row|
row.raw[/^#/] # skip rows starting with '#'
end
or ...
after_build do |model|
throw :skip if model.draft?
end
I couldn't get this to work in a reasonable amount of time, so I was wondering where you typically place your importer files in a Rails application.
I tried putting my ImportItemsCSV
in the models
directory but even then I end up getting NoMethodError - undefined method
new' for nil:NilClass:` when I try to instantiate it in a controller.
can be defined at the class level or passed at runtime
class ImportUserCSV
# ...
after_save do |user|
user.imported!
end
end
or
progress = ProgressBar.new
ImportUserCSV.new(file: da_file, after_save: -> { increment_progress_bar })
or
ImportUserCSV.new(file: da_file) do
after_save do |user|
user.update!(account: current_account)
end
end
column :published, type: Boolean
column :published_at, type: DateTime
column :reviews, type: Integer
Is there a good way to get current_user
into the context for an after_build
or after_save
?
csv-importer.rb
that requires csv_importer.rb
When loading CSV from a Input Stream, don't read the entire file. Lazy load rows instead.
This should declutter the code a bit:
column :email, to: ->(email) { email.downcase.strip if email }
column :name, to: ->(name) { name || "N/A" }
would become
column :email, to: ->(email) { email.downcase.strip }
column :name, to: ->(name) { name.presence || "N/A" }
Having a model validator like this:
validate :check_price
...
...
def check_price
if price.nil? && Spree::Config[:require_master_price]
raise 'No master variant found to infer price' unless product && product.master
raise 'Must supply price for variant or master.price for product.' if self == product.master
self.price = product.master.price
end
if price.present? && currency.nil?
self.currency = Spree::Config[:currency]
end
end
persisted_rows! method in Runner class will fail trying to save the model instead of just adding a new failure tag.
Is this gen compatible with jruby and if so is there syntax changes or setup requirements I'd need to be aware of?
Headers "first name", "First name", "first_name" should all be converted to :first_name
Once a csv file has been imported, the report object should provide a csv_file_with_errors
that is identical to the original one (same headers, same order), with only the rows that errored and with an extra column that contains the validation error.
6: column :email, to: ->(email) { email.downcase }, required: true
When I run an import with a CSV , I get an error ...
NoMethodError: undefined method `downcase' for nil:NilClass
on line 6:
I would expect this line in the CSV to simply be skipped because it is required? I could guard against the exception but then it would create a record with a blank email.
Thanks..
UPDATE: Not raising an error works and doesn't create the record. Not ideal, I think the block shouldn't be run unless email is present but it's an acceptable workaround
6: column :email, to: ->(email) { email && email.downcase }, required: true
Say you want to update records via id
. You should be able to import a csv file without an id
column to create records.
irb example:
2.1.5 :023 > str = "1,Glk,Lev \"The Black Spider\" Yashin,USSR"
=> "1,Glk,Lev \"The Black Spider\" Yashin,USSR"
2.1.5 :024 > CSV.parse(str)
CSV::MalformedCSVError: Illegal quoting in line 1.
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1857:in `block (2 levels) in shift'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1819:in `each'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1819:in `block in shift'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1779:in `loop'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1779:in `shift'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1721:in `each'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1735:in `to_a'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1735:in `read'
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/lib/ruby/2.1.0/csv.rb:1293:in `parse'
from (irb):24
from /Users/shvetsovdm/.rvm/rubies/ruby-2.1.5/bin/irb:11:in `<main>'
so, how to make it report all invalid records, thanks
Some of our users have decided to include "comments" at the top of the CSV files. I know, this sucks, and not allowed in CSV, but... is there any way we can exclude some lines, ideally I'd like to run some lambda to check if the line should be processed. Is this possible?
Thanks, I get this isn't really your fault and this would be invalid CSV but ... users.. :)
Our CSV's single row represents multiple models, which may or may not have an ActiveRelation amongst themselves. it would be awesome to have multiple models with columns mapping for each models.
It can find or create using multiple columns
# find or create by name AND website
identifier :name, :website
can be defined at the class level or passed at runtime
class ImportUserCSV
# ...
after_build do |user|
user.active = true
end
end
or
ImportUserCSV.new(file: da_file, after_build: ->(user) { user.account = current_account })
or
ImportUserCSV.new(file: da_file) do
after_build do |user|
user.account = current_account
end
end
Can I upload only CSV file in director and save it in my rails app if yes how I can only upload?
... I just wanted to say that I love you ❤️
Cheers guys, you're awesome :)
Whenever I try to use this feature, I get timeouts on production. Any suggestions on moving this to a background job (we're using AWS SQS)?
after_build blocks are executed when in :set_attributes method.
:set_attributes is called two times for each row (in :model and :find_model).
I consider this a bug because I'm expecting after_build being called only one time for each row.
If the csv file contents Japanese or Chinese, then will return nil.
When I pass in the url S3 url, I get "No such file or directory @ rb_sysopen". Does the "path" not accept a full S3 url?
csv_options[:col_sep] = [";","\t",","].sort_by{|separator| csv_sample.count(separator)}.last
I run into memory bloat when processing large files (50K+ rows). This can quickly be an issue for containerized environments. It think there is optimization potential in CSVImporter ::Runner#persist_row! and CSVImporter::Row#model. Correct me if I'm wrong, but right now the importer holds onto an ActiveRecord Model for every imported row until the import is complete.
I'll dig a bit more into this when I have the time, I just want to get the discussion going.
Given:
class User
validates :email, presence: true
end
The importer should figure that email is a required column. 😸
And the ReportMessage
should take care of generating error messages
Is it possible to combine several columns from the csv file into one model column? For example, I have: Vendor Name, Vendor Phone, Vendor Email, etc ... and want to merge into just one column Vendor, separate each by new lines instead.
column :first_name, as: "Prénom"
column :first_name, as: /name/
column :first_name, as: /prénom/i # case insensitive
column :first_name, as: ["First name", "first name", "firstname", "name"]
It's present in the README but I can't find it in the source code. Maybe just a typo for when_invalid
Is there a way I could pass an identifier to csv-importer so that a user could choose the identifer(s)?
I'm using cvs-importer to import hardware details.. lets say:
model Host
And that model has a has_many :mac_addresses relationship.
Is it possible to perform an update/create for the corresponding MacAddress entries from a column in the CSV?
I'd like to add a 3rd option to this case where the block passed uses the column (not column_definition) too. This allows to do custom conversion with metadata stored in the column name. For example the columns header is defined as "name, birthdate[%d/%m/%y], address". So the column name matches trough a regex and you can capture the metadata inside []
case to_proc.arity
when 1 # to: ->(email) { email.downcase }
model.public_send("#{column_definition.name}=", to_proc.call(csv_value))
when 2 # to: ->(published, post) { post.published_at = Time.now if published == "true" }
to_proc.call(csv_value, model)
when 3 [some code]
else
raise ArgumentError, "`to` proc can only have 1 or 2 arguments"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.