Reputation: 997
This is my code.
class Product < ActiveRecord::Base
attr_accessible :name, :price, :released_on
begin
validates :name, uniqueness: true
rescue ActiveRecord::RecordInvalid => e
render( inline: "RESCUED ActiveRecord::RecordInvalid" )
return
end
def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
all.each do |product|
csv << product.attributes.values_at(*column_names)
end
end
end
def self.import(file)
CSV.foreach(file.path , headers:true) do |row|
Product.create! row.to_hash # If we want to add a new item
end
end
end
when I save a duplicate model with same name an exception is raised
ActiveRecord::RecordInvalid in ProductsController#import
Validation failed: Name has already been taken
Rails.root: /home/deepender/396-importing-csv-and-excel/store-before
I am using rescue operation still it is not handling error? Any guesses where I am wrong.
Upvotes: 1
Views: 8008
Reputation: 2171
As Cody mentioned, do not wrap you valites in begin/rescue, because the validates method is just telling your model what need to be validated, it's not where the actual validation method is running.
Then, here's what your import method should look like :
def import(file)
CSV.foreach(file.path , headers:true) do |row|
product = Product.new(row.to_hash)
if product.save
# product valid and created
else
# invalid record here... you can inspect product.errors
end
end
Upvotes: 3
Reputation: 32758
Couple things. You don't wrap your validates
in begin/rescue
blocks. So your model should only look like:
class Product < ActiveRecord::Base
attr_accessible :name, :price, :released_on
validates :name, uniqueness: true
end
And its in the controller where you perform the validation and handle it appropriately. A sample controller might look like:
class ProductsController < ApplicationController
def create
@product = Product.new(params[:product])
if @product.valid?
@product.save
flash[:notice] = "Product created!"
redirect_to(@product) and return
else
render(:action => :new)
end
end
end
And then in your view you might render the actual errors back to the user:
# app/views/products/new.html.erb
<%= error_messages_for(@product) %>
.. rest of HTML here ..
error_messages_for
is no longer included in Rails by default and its in the gem dynamic_form
For a generic method of displaying errors see this Rails Guide:
http://guides.rubyonrails.org/active_record_validations.html#displaying-validation-errors-in-views
Upvotes: 5