Skip to content

Instantly share code, notes, and snippets.

@dmz006
Created May 16, 2013 00:05
Show Gist options
  • Save dmz006/5588448 to your computer and use it in GitHub Desktop.
Save dmz006/5588448 to your computer and use it in GitHub Desktop.
from http://railscasts.com/episodes/396-importing-csv-and-excel
class ProductImport
# switch to ActiveModel::Model in Rails 4
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
attr_accessor :file
def initialize(attributes = {})
attributes.each { |name, value| send("#{name}=", value) }
end
def persisted?
false
end
def save
if imported_products.map(&:valid?).all?
imported_products.each(&:save!)
true
else
imported_products.each_with_index do |product, index|
product.errors.full_messages.each do |message|
errors.add :base, "Row #{index+2}: #{message}"
end
end
false
end
end
def imported_products
@imported_products ||= load_imported_products
end
def load_imported_products
spreadsheet = open_spreadsheet
header = spreadsheet.row(1)
(2..spreadsheet.last_row).map do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
product = Product.find_by_id(row["id"]) || Product.new
product.attributes = row.to_hash.slice(*Product.accessible_attributes)
product
end
end
def open_spreadsheet
case File.extname(file.original_filename)
when ".csv" then Csv.new(file.path, nil, :ignore)
when ".xls" then Excel.new(file.path, nil, :ignore)
when ".xlsx" then Excelx.new(file.path, nil, :ignore)
else raise "Unknown file type: #{file.original_filename}"
end
end
end
create a new version of this paste
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment