Recording errors

I am using restful_authentication in a rails app, but I also wanted to let administrators create news users by piggybacking on the restful_authentication function.

I decided to allow csv imports for creating members in a two step process similar to this one, http://goodbadtech.com/2009/05/13/ruby-on-rails-import-csv-data-into-database/

So I import the csv using PaperClip and then process it to create users etc. I also use a rescue in case exceptions are thrown, but I would like to record these errors for display after the entire csv has been imported. I thought about creating a new model, ImportError that belonged to import, so that each csv file could have a list of error messages later on.

But I can't get the recording part to work. Users are created and stored, but the rescue action overrides everything else when errors like duplicate entries come up.

here is my controller.

class ImportsController < ApplicationController   before_filter :check_administrator_role #protect controller from anonymous users

  def new     @import = Import.new   end

  def create     @import = Import.new(params[:import])

    respond_to do |format|       if @import.save!         flash[:notice] = 'CSV data was successfully imported.'         format.html { redirect_to(@import) }       else         flash[:error] = 'CSV data import failed.'         format.html { render :action => "new" }       end     end   end

  def show     @import = Import.find(params[:id])   end

  def proc_csv     @import = Import.find(params[:id])     lines = parse_csv_file(@import.csv.path)     #lines.shift #comment this line out if your CSV file doesn't contain a header row     if lines.size > 0       @import.processed = lines.size       lines.each do |line|           new_user(line)       end       @import.save       flash[:notice] = "CSV data processing was successful."       redirect_to :action => "show", :id => @import.id     else       flash[:error] = "CSV data processing failed."       render :action => "show", :id => @import.id     end   end

private

  def parse_csv_file(path_to_csv)     lines =

    #if not installed run, sudo gem install fastercsv     #http://fastercsv.rubyforge.org/     require 'fastercsv'

    FasterCSV.foreach(path_to_csv) do |row|       lines << row     end     lines   end

  def new_user(line)           params = Hash.new           params[:user] = Hash.new           params[:user]["name"] = line[0]           params[:user]["email"] = line[1]           params[:user]["password"] = random_password           params[:user]["password_confirmation"] = params[:user] ["password"]           @user = User.new(params[:user])           member_role = Role.find_by_rolename('member')

          if @user.save!           @user.roles << member_role             else           record_error(line)            end

      rescue ActiveRecord::RecordInvalid   end

  def random_password(size = 8)     chars = (('a'..'z').to_a + ('0'..'9').to_a) - %w(i o 0 1 l 0)     (1..size).collect{|a| chars[rand(chars.size)] }.join   end

  def record_error(line)           params = Hash.new           params[:import_error] = Hash.new           params[:import_error]["import_id"] = @import.id           params[:import_error]["name"] = line[0]           params[:import_error]["email"] = line[1]           params[:import_error]["error_message"] = flash[:error]           @import_error = User.new(params[:import_error])           @import_error.save!   end

end

This else statement will never execute since if save! fails it raises an exception. Did you want to use save instead ?

Fred

Hi Fred,

You are right about the conditional statement being rubbish.

What I really want is to save users that pass the validations and any lines in the csv that fail to get skipped over, but remember the error that was generated.

Without rescue the whole action would fail.

I am just not sure how to record those errors and associate them with this particular import.

Dan

Hi Fred,

You are right about the conditional statement being rubbish.

What I really want is to save users that pass the validations and any lines in the csv that fail to get skipped over, but remember the error that was generated.

Well if you use save rather than save! it won't raise an exception if the record is invalid. If you want the individual errors they'll be in your_object.errors.

Fred