- SQlite allow database to be specified as URL (given that URI filename
interpretation was turned on on the connection.)
This commit is necessary for the read_uncommitted transaction
feature because SQLite doesn't allow to enable the shared-cache mode
if the database name is `:memory:`. It has to be a URI (`file::memory`)
Ref https://www.sqlite.org/sharedcache.html#shared_cache_and_in_memory_databases
- ### Use case
I'd like to be able to see changes made by a connection writer
within a connection reader before the writer transaction commits
(aka `read_uncommitted` transaction isolation level).
```ruby
conn1.transaction do
Dog.create(name: 'Fido')
conn2.transaction do
Dog.find(name: 'Fido') # -> Can't see the dog untill conn1 commits the transaction
end
end
```
Other adapters in Rails (mysql, postgres) already supports multiple
types of isolated db transaction.
SQLite doesn't support the 4 main ones but it supports
`read_uncommitted` and `serializable` (the default one when opening
a transaction)
### Solution
This PR allow developers to open a `read_uncommitted` transaction by
setting the PRAGMA `read_uncommitted` to true for the duration
of the transaction. That PRAGMA can only be enabled if the SQLite
connection was established with the [shared-cache mode](https://www.sqlite.org/sharedcache.html)
This feature can also benefit the framework and we could potentially
get rid of the `setup_shared_connection_pool` inside tests which
was a solution in the context of a multi-db app so that the reader
can see stuff from the open transaction writer but has some [caveats](https://github.com/rails/rails/issues/37765#event-2828609021).
### Edge case
Shared-cache mode can be enabled for in memory database as well,
however for backward compatibility reasons, SQLite only allows
to set the shared-cache mode if the database name is a URI.
It won't allow it if the database name is `:memory`; it has to be
changed to `file::memory` instead.
= This feature existed back in 2012 5e7d6bba79
but got reverted with the incentive that there was a better approach.
After discussions, we agreed that it's a useful feature for apps
that have a really large set of routes.
Co-authored-by: Yehuda Katz <wycats@gmail.com>
I added myself links to the Ruby on Rails Tutorial years ago, after
meeting Michael in a RailsConf.
By then, the book was a commercial product, but had a free online
version and I thought it could be a good resource complementing the
official documentation.
Nowadays, only a few sample chapters are available for free, and I
don't consider these links to be fair with the rest of commercial
books about Rails anymore.
This reverts commit 28e44f472d.
A limitation of Listen is that it currently only supports watching directories.
Therefore, watching `config/routes.rb` will end up watching the entire `config` directory
if we use the evented file watcher. This causes problems especially if symlinks are present
in the `config` directory.
This reverts commit 5bbb2a6521, reversing
changes made to f9e4906c37.
Reason: Since #36866, we use `azure-storage-blob` gem. So the original
description is correct.
Follow up to https://github.com/rails/rails/pull/31872
Particularly, the closing `</tt>` tag of the documented wait algorithm had a misplaced `<`. Threw in a space between `15% (0.15)` for good measure.
[ci skip]
Fix: https://github.com/rails/rails/issues/37650
The classic autoloader used to totally unregister any constant that
failed midway. Which mean `"SomeConst".constantize` was idempotent.
However Zeitwerk rely on normal `Kernel#require` behavior, which mean
that if an exception is raised during a class/module definition,
it will be left incompletely defined. For instance:
```ruby
class FooController
::DoesNotExist
def index
end
end
```
Will leave `FooController` defined, but without its `index` method.
Because of this, when silencing a NameError, it's important
to make sure the missing constant is really the one we were trying
to load.