module ImportExport::ModelMethods::ClassMethods

Public Instance Methods

acts_as_importable(options = {}) click to toggle source

any method placed here will apply to classes

# File lib/import_export.rb, line 12
def acts_as_importable(options = {})
  cattr_accessor :import_fields, :export_fields, :before_import
  self.import_fields = options[:import_fields]
  self.export_fields = options[:export_fields]
  self.before_import = options[:before_import]
  send :include, InstanceMethods
end
export() click to toggle source
# File lib/import_export.rb, line 71
def export
  export_fields = self.import_fields || self.export_fields
  ImportExport::CSV.generate do |csv|
    csv << export_fields.map{|f| f.split('.')[0]}

    self.find_each(:batch_size => 2000) do |element|
      collection = []
      export_fields.each do |field_name|
        begin
          if field_name.include?('.')
            method_names = field_name.gsub(/!/,'').split('.').compact
            sub_element = element
            method_names.each do |method_name|
              if sub_element || sub_element.respond_to?(method_name)
                sub_element = sub_element.send(method_name)
              else
                break
              end
            end
            collection << sub_element
          else
            collection << element.send(field_name)
          end
        rescue Exception => e
          Rails.logger.info ">>>>>>>>> Exception Caught ImportExport >>>>>>>>>>>"
          Rails.logger.error e.message
          Rails.logger.error e.backtrace
          collection << nil
        end
      end
      csv << collection
    end
    
  end
end
import(filename, context) click to toggle source
# File lib/import_export.rb, line 20
def import(filename, context)
  collection = []
  headers, *data  = self.read_csv(filename)
  scope_object = context[:scoped]

  ActiveRecord::Base.transaction do
    data.each_with_index do |data_row, index|
      data_row.map{|d| d.strip! if d}

      # method to modify data_row before import
      if self.before_import
        if self.respond_to? self.before_import
          self.send(self.before_import, data_row)
        else
          raise "undefined before_import method '#{self.before_import}' for #{self} class"
        end
      end

      begin
        class_or_association = scope_object ? scope_object.send(self.table_name) : self
        if key_field = context[:find_existing_by]
          key_value = data_row[index_of(key_field)]
          element = class_or_association.send("find_by_#{key_field}", key_value) || class_or_association.new
        else
          element = class_or_association.new
        end

        Rails.logger.info "#{element.new_record? ? "Creating new" : "Updating existing"} record from #{data_row.inspect}"

        self.import_fields.each_with_index do |field_name, field_index|
          if field_name.include?('.')
            assign_association(element, field_name, field_index, context, data_row)
          else
            element.send "#{field_name}=", data_row[field_index]
          end
        end

        element.save!
        collection << element
      rescue Exception => e
        e1 = e.exception("Invalid data found at line #{index + 2} : " + e.message)
        e1.set_backtrace(e.backtrace)
        Rails.logger.error e1.message
        Rails.logger.error e1.backtrace.join("\n")
        raise e1
      end
    end
  end
  return collection
end
index_of(fieldname) click to toggle source
# File lib/import_export.rb, line 120
def index_of(fieldname)
  @import_field_indices ||= {}
  @import_field_indices[fieldname] ||= self.import_fields.index{ |f| f.to_s == fieldname.to_s }
end
read_csv(filename) click to toggle source
# File lib/import_export.rb, line 107
def read_csv(filename)
  if File.exist?(filename)
    collection = ImportExport::CSV.parse(File.open(filename, 'rb'))

    collection = collection.map{|w| w} unless collection.nil?
    collection = [] if collection.nil?

    return collection
  else
    raise ArgumentError, "File does not exist."
  end
end

Protected Instance Methods

assign_association(element, field_name, field_index, context, data_row) click to toggle source
# File lib/import_export.rb, line 127
def assign_association(element, field_name, field_index, context, data_row)
  scope_object = context[:scoped]
  create_record = field_name.include?('!')
  association_name, association_attribute = field_name.gsub(/!/,'').split('.')
  assign_association_method = "assign_#{association_name}"
  association_fk = "#{association_name}_id"

  if element.respond_to?(assign_association_method)
    element.send assign_association_method, data_row, context
  elsif element.respond_to?(association_fk)
    association_class = association_name.classify.constantize

    if scope_object && scope_object.respond_to?(association_class.table_name)
      association_class = scope_object.send(association_class.table_name)
    end

    finder_method = "find_by_#{association_attribute}"
    if association_class and association_class.respond_to?(finder_method)
      e = association_class.send(finder_method, data_row[field_index])
      if e.nil? and create_record and !data_row[field_index].blank?
        e = association_class.create!(association_attribute => data_row[field_index])
      end
      element[association_fk] = e.id if e
    end
  end
end