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