16

How can I handle ActiveRecord::RecordNotUnique exception in the controller? Thanks

Edit: I'm getting that exception when generating an unique code. I can handle the exception in the application_controller.rb but what I really want is to code to be generated again and that must be done in the controller.

generate_code
@couponcode = Couponcode.new(:user_id => current_user.id, :code => @code)

Edit2:

generate_code

begin
  @couponcode = Couponcode.new(:user_id => current_user.id, :code => @code)
rescue ActiveRecord::RecordNotUnique
  #generate_code
  @code = "111-11111" 
  @couponcode = Couponcode.new(:user_id => current_user.id, :code => @code)           
end
Gaurav Sharma
  • 477
  • 9
  • 24
donald
  • 23,587
  • 42
  • 142
  • 223
  • Maybe a bit more code? I think you are getting that exception when trying to save the record and that part is not included in your example. – Heikki Jan 05 '11 at 22:24

3 Answers3

30
begin
  # do stuff
rescue ActiveRecord::RecordNotUnique
  # handle the exception however you want to
end

http://ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html

You could also use rescue_from if it's something you need to deal with often.

idlefingers
  • 31,659
  • 5
  • 82
  • 68
  • I've edited the question with the new code. I've tried without the @couponcode on the rescue and with. The error is still the same, there's still the exception not being handled. – donald Jan 05 '11 at 22:06
  • Are you sure the error is coming from the `.new` line and not where `.save` is called? The docs for [ActiveRecord::RecordNotUnique](http://api.rubyonrails.org/classes/ActiveRecord/RecordNotUnique.html) suggest it would be raised when the record is saved to the database. In any case, trying to do pretty much the same thing in a rescue block is going to lead to pain in the long run. If you're expecting the error, from a user standpoint, you need to deal with it more gracefully (such as using validations and form errors). – idlefingers Jan 05 '11 at 22:22
  • If you're not expecting the error, but it's happening a lot, you should try to get to the root of the problem, not just suppress it. Sorry for the double comment, SO comment length limitation! :) – idlefingers Jan 05 '11 at 22:23
  • 1
    It works. Thanks. I totally understand your point. But I don't know what else I can do. I'm generating unique codes and the algorithm is as unique as possible but I want to make sure the codes are not equal so I have a unique_index. If the code is not unique when saving, I have no other option to generate another code and save it. I know I have a problem if the code is not unique the second time it generates but what can I do? – donald Jan 05 '11 at 22:30
  • you should deal with that in the model then. use a `before_save` filter to check it's unique first and regenerate if needed. – idlefingers Jan 05 '11 at 22:32
  • 1
    @idlefingers: See http://stackoverflow.com/questions/4608852/rails-3-compare-unique-codes/4609020#4609020 – Heikki Jan 05 '11 at 22:39
  • the before filter can't do that either.. If you have concurrent processes (aka workers) then one could save after the test for unique is run. I'd consider revising my code generation algo. perhaps use a GUID for your code. Or make the id part of the code so create a method def get_external_code() "#{self.id}-#{self.code}" end – baash05 Apr 26 '13 at 01:49
4

Using this validation method validate_uniqueness_of does not guarantee the absence of duplicate record insertions.

You should look here

01egyk
  • 506
  • 4
  • 10
2

You can add a uniqueness validation and still have a chance to change the code without having to use rescue.

couponcode.rb

validates_uniqueness_of :code

controller:

@couponcode = Couponcode.new(:user_id => current_user.id)
begin
  couponcode.code = generate_code
  # might want to break out after a limit here
end until @couponcode.valid?
@couponcode.save

But you could also use a uuid and it would be unique without a check.

Brian Deterling
  • 13,556
  • 4
  • 55
  • 59