# config/application.rb require '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.rb class 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



