GithubHelp home page GithubHelp logo

csv-importer's Introduction

csv-importer's People

Contributors

brain-geek avatar danielweinmann avatar ferdinandrosario avatar macfanatic avatar maurycy avatar mltsy avatar paulodeleo avatar pcreux avatar perezperret avatar pnomolos avatar scalvo avatar stas avatar stevenou avatar tracyloisel avatar xtina-starr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

csv-importer's Issues

Demo?

Thanks for the CSV importer. Maybe asking for too much but is there a demo site for this? :)

Empty Row Column at beginning of csv gives an error.

When ever I have a file like in the image below, with an empty row above the headers and a empty column before the first one it breaks the importer with an error. i.e I get a 'email column is missing' is this a known issue? or am I missing something?

csv_example

Using after_save in block change class after_save_blocks array

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

Postgresql Array format

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

Add i18n to messages

All messages, such as The following columns are required: should be put into locale files, so that could be replaced on the client side.

Implement skip or abort

Current behavior is "skip".

We should wrap all imports in a transaction.

When selecting abort, we should call save!

Add mechanism to skip row

skip_if do |row|
  row.raw[/^#/] # skip rows starting with '#'
end

or ...

after_build do |model|
  throw :skip if model.draft?
end

Importer class never found

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 methodnew' for nil:NilClass:` when I try to instantiate it in a controller.

add "after_save" callback

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

Release gem v0.1

  • add missing infos to gemspec
  • add csv-importer.rb that requires csv_importer.rb

Lazy load if possible

When loading CSV from a Input Stream, don't read the entire file. Lazy load rows instead.

Empty cells should return empty strings instead of nil

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" }

Exception when model.save fails

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.

Jruby support?

Is this gen compatible with jruby and if so is there syntax changes or setup requirements I'd need to be aware of?

Generate CSV file with errors

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.

Error on importing with missing required field

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

CSV::MalformedCSVError: Illegal quoting on a line like 1,Glk,Lev "The Black Spider" Yashin,USSR

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>'

CSV files with comments

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.. :)

Multiple models to be used for a single row

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.

add after_build callback

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

Upload file

Can I upload only CSV file in director and save it in my rails app if yes how I can only upload?

Timeouts

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)?

Duplicate call to after_build blocks

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.

find separator

csv_options[:col_sep] = [";","\t",","].sort_by{|separator| csv_sample.count(separator)}.last

Memory bloat when processing large files

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.

Combine multiple columns into one

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.

handling of model associations in an import?

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?

Pass Column as parameter in "to" procs

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"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.