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:

https://groups.google.com/forum/?fromgroups#!msg/sequel-talk/VjfJcTD6s3w/Lbrc2RqVuu8J <https://groups.google.com/forum/?fromgroups#%21msg/sequel-talk/VjfJcTD6s3w/Lbrc2RqVuu8J>

Here is how sandbox is handled by ActiveRecord:

activerecord/lib/active_record/railties/console_sandbox.rb:

ActiveRecord::Base.connection.increment_open_transactions
ActiveRecord::Base.connection.begin_db_transaction
at_exit do
   ActiveRecord::Base.connection.rollback_db_transaction
   ActiveRecord::Base.connection.decrement_open_transactions
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[1]
  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.

--
You received this message because you are subscribed to the Google Groups "Ruby on 
Rails: Core" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en.

Reply via email to