<commit_before>class CsvImporter
  attr_reader :saved_records, :errors, :response_status

  def initialize(args)
    ArgsValidator.validate(params: args,
                           required: [:file_path, :model],
                           exclusive: [:file_path, :model, :global_attributes],
                           class: self.class)
    @file_path = args[:file_path]
    @model = args[:model]
    @global_attributes = args[:global_attributes] || {}
    @saved_records = []
    @errors = []
    validate_setup
  end

  def import
    if errors.present?
      self.response_status = :unprocessable_entity
      return
    end
    ActiveRecord::Base.transaction do
      records.each do |record|
        if record.save
          saved_records << record
        else
          errors << [record.attributes.compact, record.errors.full_messages]
          self.response_status = :unprocessable_entity
        end
      end
      raise ActiveRecord::Rollback if response_status
    end
    self.response_status ||= :created
  end

  private

  attr_reader :file_path, :model, :global_attributes
  attr_writer :response_status

  def records
    @records ||= processed_attributes.map { |attributes| klass.new(global_attributes.merge(attributes)) }
  end

  def processed_attributes
    @processed_attributes ||= SmarterCSV.process(file, key_mapping: key_mapping)
  end

  def file
    @file ||= FileStore.read(file_path)
  end

  def key_mapping
    params_class.key_mapping
  end

  def params_class
    @params_class ||= "#{klass}Parameters".constantize
  end

  def klass<commit_msg>In CsvImporter, add automatic row separator detection to SmarterCSV processing.<commit_after>class CsvImporter
  attr_reader :saved_records, :errors, :response_status

  def initialize(args)
    ArgsValidator.validate(params: args,
                           required: [:file_path, :model],
                           exclusive: [:file_path, :model, :global_attributes],
                           class: self.class)
    @file_path = args[:file_path]
    @model = args[:model]
    @global_attributes = args[:global_attributes] || {}
    @saved_records = []
    @errors = []
    validate_setup
  end

  def import
    if errors.present?
      self.response_status = :unprocessable_entity
      return
    end
    ActiveRecord::Base.transaction do
      records.each do |record|
        if record.save
          saved_records << record
        else
          errors << [record.attributes.compact, record.errors.full_messages]
          self.response_status = :unprocessable_entity
        end
      end
      raise ActiveRecord::Rollback if response_status
    end
    self.response_status ||= :created
  end

  private

  attr_reader :file_path, :model, :global_attributes
  attr_writer :response_status

  def records
    @records ||= processed_attributes.map { |attributes| klass.new(global_attributes.merge(attributes)) }
  end

  def processed_attributes
    @processed_attributes ||= SmarterCSV.process(file, key_mapping: key_mapping, row_sep: :auto)
  end

  def file
    @file ||= FileStore.read(file_path)
  end

  def key_mapping
    params_class.key_mapping
  end

  def params_class
    @params_class ||= "#{klass}Parameters".constantize
  end

  def klass
{'fraction_non_alphanumeric': 0.08830769230769231, 'fraction_numerical': 0.0, 'mean_word_length': 2.8202115158636896, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6410069', 'n_tokens_mistral': 950, 'n_tokens_neox': 929, 'n_words': 208}