Skip to content

Instantly share code, notes, and snippets.

@chrisconley
Created June 10, 2010 14:06
Show Gist options
  • Save chrisconley/433042 to your computer and use it in GitHub Desktop.
Save chrisconley/433042 to your computer and use it in GitHub Desktop.
require 'faster_csv'
class FasterCSV
class Table
def remove_blank_columns
original_mode_method = "by_#{self.mode}!".to_sym
by_col!.delete_if{|header, values| header.blank?}.send(original_mode_method)
end
def remove_blank_rows
original_mode_method = "by_#{self.mode}!".to_sym
by_row!.delete_if {|r| r.to_s.match(/^[\s\,]+$/)}.send(original_mode_method)
end
end
end
class ActiveRecordCsvImporter < TablelessActiveRecord
attr_accessor :file, :ar_model
attr_accessor :csv_table
validates_presence_of :file, :ar_model, :message => 'is a required parameter'
def validate
parse_file
validate_records if has_been_parsed?
end
def validate_records
csv_table.each do |row|
record = ar_model.new(row.to_hash)
errors.add(row[0], record.errors.full_messages) if !record.valid?
end
end
def parse_file
begin
csv = file.is_a?(String) ? File.open(file).read : file.read
@csv_table = FasterCSV.parse(csv, :headers => true, :skip_blanks => true)
@csv_table.remove_blank_columns
@csv_table.remove_blank_rows
rescue StandardError => e
errors.add :file, "could not be parsed because #{e.message}"
end
end
def has_been_parsed?
csv_table && csv_table.is_a?(FasterCSV::Table)
end
end
class TablelessActiveRecord < ActiveRecord::Base
def self.columns
@columns ||= [];
end
def self.column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
end
# Override the save method to prevent exceptions.
def save(validate = true)
validate ? valid? : true
end
end
class TranslationImporter < ActiveRecordCsvImporter
attr_accessor :locale
validates_presence_of :locale, :message => 'is a required parameter'
def validate_records
csv_table.each do |row|
record = ar_model.new(row.to_hash.merge(:locale => locale))
errors.add(row[0], record.errors.full_messages) if !record.valid?
end
end
def import!
csv_table.each do |row|
attrs = row.to_hash.merge(:locale => locale)
Translation.update_or_create(attrs)
end
end
def ar_model
Translation
end
end
class TranslationImporterController < ApplicationController
def new
@importer = TranslationImporter.new
end
def process_csv
@importer = TranslationImporter.new(params[:importer])
if @importer.valid?
@importer.import!
flash[:notice] = 'The translations have been imported!'
redirect_to new_translation_importer_url
else
render :action => 'new'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment