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


any advice will be appreciated.

Thanks,

Dan

On Aug 5, 12:08 am, DanC [email protected] wrote:

      if @user.save!
      @user.roles << member_role
        else
      record_error(line)
       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

On Aug 5, 9:44 am, DanC [email protected] wrote:

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