Importing and Exporting CSV Data

#35 Importing and Exporting CSV Data
6/26/2016

Summary

Basics on importing and exporting CSV Data using Ruby and without gems.
4
ruby rails data

Summary

config/application.rbrequire 'csv'
config/routes.rb  resources :products do
    collection { post :import }
  end
products_controller.rb  def index
    @products = Product.all
    respond_to do |format|
      format.html
      format.csv { send_data @products.to_csv(['name', 'category', 'price']) }
    end
  end

  def import
    Product.import(params[:file])
    redirect_to root_url, notice: "Products imported."
  end
product.rbclass Product < ApplicationRecord
  def self.to_csv(fields = column_names, options = {})
    CSV.generate(options) do |csv|
      csv << fields
      all.each do |product|
        csv << product.attributes.values_at(*fields)
      end
    end
  end

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      product_hash = row.to_hash
      product = find_or_create_by!(name: product_hash['name'], category: product_hash['category'])
      product.update_attributes(product_hash)
    end
  end
end
index.html.erb

<%= form_tag import_products_path, multipart: true, class: 'form-inline' do %>   <div class="form-group">     <%= link_to "Export CSV", products_path(format: "csv"), class: 'btn btn-primary' %>   </div>   <div class="form-group">     <%= file_field_tag :file, class: '' %>   </div>      <div class="form-group">     <%= submit_tag "Import CSV", class: 'btn btn-info' %>   </div> <% end %>


If you need to background process the file import, check out the ActiveJob branch of this episode's source

https://github.com/driftingruby/035-importing-and-exporting-csv-data/compare/ActiveJobs?expand=1


635114?v=3&s=64
kobaltz said 11 months ago:

Have a look at this branch compare. (https://github.com/driftingrub...

You basically will need to temporarily create a file to store it and pass the path to ActiveJob. While this is currently working on local filestore, it can also work with S3 or fog.

3416976?v=3&s=64
zulhfreelancer said 11 months ago:

I didn't understand this 2 parts:

1. product.attributes.values_at(*fields) - what actually *fields means here?
2. Why we use find_or_create_by! instead of find_or_create_by?

635114?v=3&s=64
kobaltz said 11 months ago:

The * is a splat operator. So, take the following example.

[2] pry(main)> fields
=> ["first_name", "last_name"]
[3] pry(main)> User.first.attributes.values_at(fields)
User Load (0.5ms)SELECT`users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> [nil]
[4] pry(main)> User.first.attributes.values_at(*fields)
User Load (0.5ms)SELECT`users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> ["System", "Administrator"]

http://blog.honeybadger.io/rub...

The ! at the end of find_or_create_by will raise an exception on validation errors.

3416976?v=3&s=64
zulhfreelancer said 11 months ago:

Thanks man.

7466259?v=3&s=64
osazemeu said 5 months ago:

How do I export nested attributes to CSV? i.e. I have a primary contact model, and I nested secondary contact into it. How do I export both as single CSV file?

3710958?v=3&s=64
denegny said about 1 month ago:

on upload file will be сontrol of exceptions

  def import
begin
Product.import(params[:file])
redirect_to root_url, notice: "Products successfully imported."
rescue
redirect_to root_url, notice: "Invalid CSV file format."
end
end

Login to Comment