Make #with_lock as expressive as calling #transaction and #lock!
individually to enable behavior like so:
person.with_lock("FOR UPDATE NOWAIT", requires_new: true) do
...
end
Helps teams who prefer #with_lock over #lock! to ensure the lock is
taken out within a transaction, even when advanced transaction control
is required without requiring redundant transaction blocks.
Something I've seen on many Rails + PostgreSQL apps is that the only reason `structure.sql` is used instead of `schema.rb` is to support custom [enum types](https://www.postgresql.org/docs/current/datatype-enum.html). Enum types are great for type integrity and they work well with [`ActiveRecord::Enum`](https://api.rubyonrails.org/classes/ActiveRecord/Enum.html). And schema.rb is much easier to use than structure.sql. It would be great if more PostgreSQL projects could use schema.rb. To enable that, this PR adds native support for PostgreSQL enums in schema.rb.
In migrations, you can now use `create_enum` to add a new enum type, and `t.enum` to add a column:
```ruby
def up
# note that enums cannot be dropped
create_enum :mood, ["happy", "sad"]
change_table :cats do |t|
t.enum :current_mood, enum_type: "mood", default: "happy", null: false
end
end
```
The enum definitions and enum columns will be presented in schema.rb, so you can load them into a test database and they'll work correctly.
-------------------------------
It's worth noting again that this is *not* compatible with other database engines. So this will not work with `rails db:system:change` (or the equivalent manual process). My assumption is that this is a fairly unlikely thing to happen midway through a project - as opposed to when the app is first spun up - so it's safe to assume that once you've dug into using enums you probably aren't going to switch databases on a whim.
For what it's worth, the MySQL adapter also supports enums (https://github.com/rails/rails/blob/main/activerecord/test/cases/adapters/mysql2/enum_test.rb) but the syntax doesn't look easy to translate (I also don't have much MySQL experience so don't really want to wade into this).
"encrypted" implies *symmetrically (reversibly)* encrypted, using something like AES.
e.g. see the other usages of "encrypt" in this security doc:
> unencrypted wireless LAN
> Rails encrypts cookies by default
> For more details on key rotation with encrypted and signed messages
> Rails stores secrets in `config/credentials.yml.enc`, which is
encrypted and hence cannot be edited directly
All of these usages are referring to symmetric encryption.
Additionally, all three of the referenced implementations (devise,
authlogic, and rails' own has_secure_password), use password _hashing_
not a symmetric encryption.
[Authlogic notes this](0cdd582ba5/lib/authlogic/acts_as_authentic/password.rb (L105))
> Reversible functions like AES256 are the worst choice, and we no longer support them.
Alternatively, I'd be fine with doubling down on the term "digest" if
there's a strong preference for that instead of "hash". From my
perspective they're synonyms, and equally distinct from "encrypt".
Internally the [Rails has_secure_password
implementation](83217025a1/activemodel/lib/active_model/secure_password.rb (L7))
refers to both "hash" and "digest".
For links to work in SystemTestCases, it requires the `host` to be added
to the `default_url_options`. Since
78c734386cddf5ee533ad1915d3769b9cc1be3a2 this is done by looking at
`Capybara.app_host` or `Capybara.current_session.server_url`.
This works correctly when using the Selenium webdriver, as Capybara sets
either the `Capybara.app_host` or the `Capybara.current_session.server_url`.
However the Capybara RackTest driver uses paths instead of URL's, so it doesn't
set Capybara.app_host or Capybara.current_session.server_url.
For SystemTestCase to work for the RackTest driver a host has to be
available for url options. We can fallback to "http://127.0.0.1" which
was the default before 78c734386cddf5ee533ad1915d3769b9cc1be3a2.