Rodrigo Rosenfeld Rosas
2012-Apr-23 22:39 UTC
[rspec-users] How to modify database inside a transaction in before(:all)?
I have a set of examples that should run with a specific set of records in the database. Since setting those records is an expensive operation I''d like to perform it just once per context. For example: context ''sample tree'' do before(:all) { create_tree_records } example ... end The problem with this is that while before(:each) and the examples will run in a transaction that will be rolled back at the end of each example, that won''t happen to the records created/modified by the before(:all) block. It seems my database vendor (PostgreSQL) supports nested transactions (savepoints): http://www.postgresql.org/about/ I should also notice that I''m using Sequel and it seems that transactions are reentrant in Sequel: http://cheat.errtheblog.com/s/sequel/ Database#transaction is re-entrant: DB.transaction do # BEGIN issued only here DB.transaction dataset << {:first_name => ''Inigo'', :last_name => ''Montoya''} end end # COMMIT issued only here So, this logic wouldn''t work for me. I need a save point in a before(:all), so that I''d restore it on a before(:each). Is there any recommendation to make this work in my specs? Thanks in advance, Rodrigo. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120423/2054867f/attachment-0001.html>
David Chelimsky
2012-Apr-23 23:04 UTC
[rspec-users] How to modify database inside a transaction in before(:all)?
On Mon, Apr 23, 2012 at 5:39 PM, Rodrigo Rosenfeld Rosas <rr.rosas at gmail.com> wrote:> I have a set of examples that should run with a specific set of records in > the database. > > Since setting those records is an expensive operation I''d like to perform it > just once per context. > > For example: > > context ''sample tree'' do > ??? before(:all) { create_tree_records } > > ??? example ... > end > > The problem with this is that while before(:each) and the examples will run > in a transaction that will be rolled back at the end of each example, that > won''t happen to the records created/modified by the before(:all) block. > > It seems my database vendor (PostgreSQL) supports nested transactions > (savepoints): > > http://www.postgresql.org/about/ > > I should also notice that I''m using Sequel and it seems that transactions > are reentrant in Sequel: > > http://cheat.errtheblog.com/s/sequel/ > > Database#transaction is re-entrant: > > ? DB.transaction do # BEGIN issued only here > ??? DB.transaction > ????? dataset << {:first_name => ''Inigo'', :last_name => ''Montoya''} > ??? end > end # COMMIT issued only here > > So, this logic wouldn''t work for me. I need a save point in a before(:all), > so that I''d restore it on a before(:each). > > Is there any recommendation to make this work in my specs?Nothing built into RSpec now, but you could disable the Rails transaction management and use DatabaseCleaner on your own. This is currently being discussed in https://github.com/rspec/rspec-rails/issues/496 as well. Feel free to join that convo. Cheers, David> > Thanks in advance, > Rodrigo.
Rodrigo Rosenfeld Rosas
2012-Apr-24 02:22 UTC
[rspec-users] How to modify database inside a transaction in before(:all)?
Em 23-04-2012 20:04, David Chelimsky escreveu:> On Mon, Apr 23, 2012 at 5:39 PM, Rodrigo Rosenfeld Rosas > <rr.rosas at gmail.com> wrote: >> I have a set of examples that should run with a specific set of records in >> the database. >> >> Since setting those records is an expensive operation I''d like to perform it >> just once per context. >> >> For example: >> >> context ''sample tree'' do >> before(:all) { create_tree_records } >> >> example ... >> end >> >> The problem with this is that while before(:each) and the examples will run >> in a transaction that will be rolled back at the end of each example, that >> won''t happen to the records created/modified by the before(:all) block. >> >> It seems my database vendor (PostgreSQL) supports nested transactions >> (savepoints): >> >> http://www.postgresql.org/about/ >> >> I should also notice that I''m using Sequel and it seems that transactions >> are reentrant in Sequel: >> >> http://cheat.errtheblog.com/s/sequel/ >> >> Database#transaction is re-entrant: >> >> DB.transaction do # BEGIN issued only here >> DB.transaction >> dataset<< {:first_name => ''Inigo'', :last_name => ''Montoya''} >> end >> end # COMMIT issued only here >> >> So, this logic wouldn''t work for me. I need a save point in a before(:all), >> so that I''d restore it on a before(:each). >> >> Is there any recommendation to make this work in my specs? > Nothing built into RSpec now, but you could disable the Rails > transaction management and use DatabaseCleaner on your own.Actually I''m not using the Rails transaction management anymore since I moved all my models to Sequel::Model. I''ve created a section in my last article on how to setup Sequel, Rails and RSpec. Please check the RSpec section: http://rosenfeld.herokuapp.com/en/articles/2012-04-18-getting-started-with-sequel-in-rails The issue with using DatabaseCleaner is that it doesn''t support nested transactions too. And I don''t want to use the truncate strategy as there are some tables that shouldn''t be cleared.> This is currently being discussed in > https://github.com/rspec/rspec-rails/issues/496 as well. Feel free to > join that convo.I don''t know if this is possible to accomplish with all supported databases. Maybe there is a simpler approach for PostgreSQL by using savepoints. I''ll make some experiments similar to the approach I''ve used in my article to create those savepoints. I''d just like to know if there was something already done following this idea, but if there isn''t, I guess I''ll have to do it myself :( Thank you very much for your (always) fast response :) Cheers, Rodrigo. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120423/ad283102/attachment.html>