Recently I’ve found out some mentions to the “–sandbox” parameter
to the “rails console” command.
And I found the idea interesting, but since I'm using Sequel instead
of ActiveRecord I guessed this wouldn’t work for me.
But after talking about this subject in the Sequel mailing list,
Jeremy Evans has brought to my attention that there are some issues
with the current approach taken by ActiveRecord.
In case you're curious about the full thread:
Here is how sandbox is handled by ActiveRecord:
ActiveRecord::Base.connection.increment_open_transactions ActiveRecord::Base.connection.begin_db_transaction at_exit do
end This only handles the default database as noticed by Jeremy. If
you have models relying on different databases, only the default
one will be sandboxed.
Additionally, there is another design issue. For example, Sequel
was designed in a way that it won’t allow users to directly
manipulate connections and control where to start and end
transactions. So it only provides a block-based approach:
Here is how this would be implemented in Sequel (assuming a decent
database like PostgreSQL that supports savepoints - if that is not
the case, just remove the :savepoint option):
DB.transaction(savepoint: true, rollback: :always) do # sandboxed database access here: u = User u.name = 'Changed' u.save_changes end I have a similar issue with the design of RSpec lack of an
around(:all) filter similar to around(:each) that won’t allow me
to use savepoints to restore the database state when creating
common data in a before(:all) section of some contexts.
Sequel does support an "after_connect" hook so that it could be
used to make sure the connection is inside a transaction when it
is created. Maybe ActiveRecord could provide something similar and
use it instead for dealing with a sandboxed application.
Another issue with the current approach is that if you change some
database data inside a thread, I guess it would spawn a new
connection that wouldn’t be sandboxed. Is that right?
Any thoughts about this? Cheers, Rodrigo.