To prevent duplicate values in the DBMS I use a unique index on those columns. I am testing that duplicate values cannot, in fact, be added. This is the cucumber scenario: Scenario: The legal name must be unique Given I do have a user named "admin" And the user named "admin" is authenticated And the user named "admin" is authorized to "add" "entities" And I do have an entity named "Myuser" And the entity named "Myuser" has a legal name "Myuser Legal Name" When they visit the add a new entity page And they enter valid entity data And they enter the entity legal name "MyUser LEGAL NAME" And I press "Create" Then they should see a save error message This is the step definition that should be triggered: When /should see a save error message/ do response.body.should =~ /errors? prohibited this (.*) from being saved/im end But what happens is that SQLite3 throws an SQL exception: SQLite3::SQLException: column entity_legal_name is not unique:...; that is not caught by this controller: def create @entity = Entity.new(params[:entity]) # need this to strip out observer attributes for datebalks plugin # see config/initializers/hash_addins.rb @client = @entity.build_client(params[:client].datebalk!) respond_to do |format| if @entity.save flash[:notice] = ''Client was successfully created.'' format.html { redirect_to(@client) } format.xml { render :xml => @client, :status => :created, :location => @client } else format.html { render :action => "new" } format.xml { render :xml => @client.errors, :status => :unprocessable_entity } end end I thought, probably incorrectly, that when #save is called then any errors are returned to the controller to handle. This is evidently not happening so can someone tell me how this is supposed to be handled? -- Posted via http://www.ruby-forum.com/.
ActiveRecord doesn''t know anything about db constraint errors. If one is violated, the error propagates up in the form of an exception. Put a validates_uniqueness_of :login_name on your User class, and you''ll get the behavior you want. You can keep the db constraint in as a safety net against possible race conditions at the app layer. Pat On Mar 9, 2009, at 12:36 PM, James Byrne wrote:> To prevent duplicate values in the DBMS I use a unique index on those > columns. I am testing that duplicate values cannot, in fact, be > added. > > This is the cucumber scenario: > > Scenario: The legal name must be unique > Given I do have a user named "admin" > And the user named "admin" is authenticated > And the user named "admin" is authorized to "add" "entities" > And I do have an entity named "Myuser" > And the entity named "Myuser" has a legal name "Myuser Legal > Name" > When they visit the add a new entity page > And they enter valid entity data > And they enter the entity legal name "MyUser LEGAL NAME" > And I press "Create" > Then they should see a save error message > > This is the step definition that should be triggered: > > When /should see a save error message/ do > response.body.should =~ /errors? prohibited this (.*) from being > saved/im > end > > But what happens is that SQLite3 throws an SQL exception: > SQLite3::SQLException: column entity_legal_name is not unique:...; > > that is not caught by this controller: > > def create > @entity = Entity.new(params[:entity]) > > # need this to strip out observer attributes for datebalks plugin > # see config/initializers/hash_addins.rb > > @client = @entity.build_client(params[:client].datebalk!) > > respond_to do |format| > if @entity.save > flash[:notice] = ''Client was successfully created.'' > format.html { redirect_to(@client) } > format.xml { render :xml => @client, > :status => :created, :location => @client } > else > format.html { render :action => "new" } > format.xml { render :xml => @client.errors, > :status => :unprocessable_entity } > end > end > > I thought, probably incorrectly, that when #save is called then any > errors are returned to the controller to handle. This is evidently > not > happening so can someone tell me how this is supposed to be handled? > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
James Byrne wrote: Q.> To prevent duplicate values in the DBMS I use a unique index on those > columns. I am testing that duplicate values cannot, in fact, be added.> I thought, probably incorrectly, that when #save is called then any > errors are returned to the controller to handle. This is evidently not > happening so can someone tell me how this is supposed to be handled?A. rescue ActiveRecord::StatementInvalid -- Posted via http://www.ruby-forum.com/.
Pat Maddox wrote:> ActiveRecord doesn''t know anything about db constraint errors. If one > is violated, the error propagates up in the form of an exception. >I realize that, but the exception is of the ActiveRecord:StatementInvalid class, which I should be able to catch in the controller with a rescue clause. But, I am not getting this to work at the moment. I thought that this should at least produce some out put but it never does: def create @entity = Entity.new(params[:entity]) ... respond_to do |format| ... end end rescue => my_exception puts "Rescue clause invoked!" puts my_exception end For now, all I want is to see the rescue clause invoked, but it is not. have I put this clause in the wrong place? Am I specifying it wrong? -- Posted via http://www.ruby-forum.com/.
On Mar 9, 2009, at 4:53 PM, James Byrne wrote:> Pat Maddox wrote: >> ActiveRecord doesn''t know anything about db constraint errors. If >> one >> is violated, the error propagates up in the form of an exception. >> > > I realize that, but the exception is of the > ActiveRecord:StatementInvalid class, which I should be able to catch > in > the controller with a rescue clause. But, I am not getting this to > work > at the moment. I thought that this should at least produce some out > put > but it never does: > > > def create > @entity = Entity.new(params[:entity]) > ... > respond_to do |format| > ... > end > end > rescue => my_exception > puts "Rescue clause invoked!" > puts my_exception > end > > > For now, all I want is to see the rescue clause invoked, but it is > not. > have I put this clause in the wrong place? Am I specifying it wrong?You can try "rescue Exception" which rescues from all exceptions, not just ones which inherit from StandardError. (rescue without an explicit error class *only* rescues from StandardExceptions and error classes which derive from it): http://gist.github.com/76474 Also - I believe this only works in 1.8.6 and above, so if you''re still on 1.8.5 I''d recommend an upgrade. Scott> > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
>> ActiveRecord doesn''t know anything about db constraint errors. If >> one >> is violated, the error propagates up in the form of an exception. >> > > I realize that, but the exception is of the > ActiveRecord:StatementInvalid class, which I should be able to catch > in > the controller with a rescue clause. But, I am not getting this to > work > at the moment. I thought that this should at least produce some out > put > but it never does: > > > def create > @entity = Entity.new(params[:entity]) > ... > respond_to do |format| > ... > end > end > rescue => my_exception > puts "Rescue clause invoked!" > puts my_exception > end > > > For now, all I want is to see the rescue clause invoked, but it is > not. > have I put this clause in the wrong place? Am I specifying it wrong?Just a stab in the dark, but I haven''t seen any mention of calling save vs. save!. save just puts any errors in the model, save! will raise the exception if there are any errors. That may not be the case for ActiveRecord:StatementInvalid exception, but I thought i''d mention it anyway. timg
Tim Glen wrote:> Just a stab in the dark, but I haven''t seen any mention of calling > save vs. save!. save just puts any errors in the model, save! will > raise the exception if there are any errors. That may not be the case > for ActiveRecord:StatementInvalid exception, but I thought i''d mention > it anyway. > > timgI wondered about this but I think that since the DBMS exception is not being trapped at all that it makes no difference. However, I will check if if it does or not anyway. and Scott Taylor wrote:> You can try "rescue Exception" which rescues from all exceptions, not > just ones which inherit from StandardError.Tried that one and it did not work either.> Also - I believe this only works in 1.8.6 and above, so if you''re > still on 1.8.5 I''d recommend an upgrade.This may be the case. The target host runs CentOS-5.3 which ships with Ruby-1.8.5. I will see if I get different results on a 1.8.6 machine. -- Posted via http://www.ruby-forum.com/.
>> Just a stab in the dark, but I haven''t seen any mention of calling >> save vs. save!. save just puts any errors in the model, save! will >> raise the exception if there are any errors. That may not be the case >> for ActiveRecord:StatementInvalid exception, but I thought i''d >> mention >> it anyway.> I wondered about this but I think that since the DBMS exception is not > being trapped at all that it makes no difference. However, I will > check > if if it does or not anyway.Right - this is from the validates_uniqueness_of documentation: # When the database catches such a duplicate insertion, # ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid # exception. You can either choose to let this error propagate (which # will result in the default Rails exception page being shown), or you # can catch it and restart the transaction (e.g. by telling the user # that the title already exists, and asking him to re-enter the title). # This technique is also known as optimistic concurrency control: # http://en.wikipedia.org/wiki/Optimistic_concurrency_control so it _should_ be bubbling through. Odd that it would change in Ruby 1.8.6, but it''s worth a try. timg
On Mar 9, 2009, at 1:53 PM, James Byrne wrote:> Pat Maddox wrote: >> ActiveRecord doesn''t know anything about db constraint errors. If >> one >> is violated, the error propagates up in the form of an exception. >> > > I realize that, but the exception is of the > ActiveRecord:StatementInvalid class, which I should be able to catch > in > the controller with a rescue clause. But, I am not getting this to > work > at the moment.Not sure what your problem is. Here''s a gist that demonstrates what you''re trying to do, and works fine. http://gist.github.com/76667 Pat
Pat Maddox wrote:> > Not sure what your problem is. Here''s a gist that demonstrates what > you''re trying to do, and works fine. http://gist.github.com/76667 > > PatI do not know what I am doing wrong either. I tried much the same thing as you suggest last night in the console:>> def my_exception(x=false) >> raise ActiveRecord::StatementInvalid if x >> puts "No Exception" >> rescue ActiveRecord::StatementInvalid >> puts "exception rescued" >> end=> nil>> my_exception(false)No Exception => nil>> my_exception(true)exception rescued => nil So, my version of Ruby has nothing to do with whatever is happening. I will poke at things some more and see if I can discover what my misunderstanding is. It has to be something simple that I just do not see at the moment. -- Posted via http://www.ruby-forum.com/.
James Byrne wrote:> > I do not know what I am doing wrong either. I tried much the same thing > as you suggest last night in the console:Well, whatever I was doing wrong I seem to have fixed it. Things now seem to be working as I intended. -- Posted via http://www.ruby-forum.com/.