Commit Graph

2733 Commits

Author SHA1 Message Date
Ruy R. 71e5dc35c4
[#52698] Add `TimeZoneConverter#==` method, so objects will be properly...
compared by their type, scale, limit & precision.
2024-08-27 08:36:34 -03:00
Zacharias Knudsen 1ecb91bb38
Add support for SQLite3 full-text-search and other virtual tables.
Previously, adding sqlite3 virtual tables messed up `schema.rb`.

Now, virtual tables can safely be added using `create_virtual_table`.
2024-08-23 22:13:00 +00:00
Donal McBreen 6f79f25321
Decryption casting v2 revert (#52693)
* Revert "Switch back to DelegateClass(ActiveModel::Type::Value)"

This reverts commit 91745df899.

* Revert "Update docs and changelog"

This reverts commit b234a94e56.

* Revert "Nest encrypted attribute types within serialized types"

This reverts commit 6a27e7b2f9.

* Revert "Encryption casting with `encrypts` before `serialize`"

This reverts commit 4dd2b22efe.

Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
2024-08-23 08:27:49 -07:00
Trevor Vallender 4b2174d674
Allow use of alternative database interfaces
The CLI tool used as a database interface is now specified and
customisable via ActiveRecord.database_cli.

This specifies the current defaults but allows them to be overridden by
users. It continues to accept array values to allow fallback options.
2024-08-22 17:20:37 +00:00
justin talbott fba7ef0369
support dumping PostgreSQL partitioning options to `schema.rb` 2024-08-22 16:23:06 +00:00
Donal McBreen 9c8390032c
Encryption casting with `encrypts` before `serialize` (#52650)
* Encryption casting with `encrypts` before `serialize`

A demonstration of how we can simplify encryption serialization and
deserialization if we call `encrypts` before `serialize`.

Calling cast_type.deserialize before decrypting fixes the issue where
binary data cannot be decrypted on PostgreSQL.

We would need to update the docs to recommend that `encrypts` is called
before `serialize` to take advantage of this and possibly raise an error
if they are called the other way round.

* Nest encrypted attribute types within serialized types

Make the order in which `serializes :foo` and `encrypts :foo` are called
irrelevant by always nesting the encrypted attribute type inside the
serialized type.

This required switching from `DelegateClass` to `SimpleDelegator` so
that object we are delegating to can be replaced.

To ensure that the serialized type survives YAML serialization (there's
a test for this), we need to implement init_with to call __setobj__.

* Update docs and changelog

* Switch back to DelegateClass(ActiveModel::Type::Value)

Thanks to @rafaelfranca for the suggestion.
2024-08-22 12:28:32 +02:00
Sean Doyle e9ee137d8b
Infer default `:inverse_of` option for `delegated_type`
Prior to this commit, delegated types were unable to infer their inverse
associations, so saving records built with the generated
`#build_ASSOCIATION` methods weren't writing to all the necessary
places. For example:

```ruby
entry = Entry.create! entryable: Message.new(subject: "Hello world!")
entry.message.subject # => "Hello world!"

entry.build_entryable(subject: "Goodbye world!").save!
entry.reload.message.subject # => "Hello world!"
```

The fact that the `Entry` test model declared a `delegated_type
:entryable` definition with `types: %w[ Message Comment ]` was never
reciprocated in the appropriate models.

In order to pass the tests, this commit needed to define the
corresponding `has_one :entry` associations. To do so, introduce the
`Entryable` concern in the same style as the one mentioned in the
documentation. The same extraction is made for a `UuidEntryable` concern
mixed into `UuidMessage` and `UuidComment`.

Unfortunately, defining `delegated_type :thing, types: %w[ Post ]` was
more tricky to fix. The `Post` test model is widely used, so defining a
`has_one` had farther-reaching effects than intended. To resolve that
issue, this commit redefines `:thing` to use `types: %w[ Essay ]`, which
has much fewer unintended side effects.
2024-08-21 19:18:29 +00:00
Stephen Drew 1823d4ab7a Add support for ActiveRecord::Point type casts using hash values
This allows ActiveRecord::Point to be cast or serialized from a hash
with :x and :y keys of numeric values, mirroring the functionality
of existing casts for string and array values. Both string and symbol
keys are supported.
2024-08-20 16:53:07 -06:00
Xavier Noria cffb642a0c Revise punctuation in CHANGELOG entry 2024-08-17 09:21:46 +02:00
Stephen Margheim 2976d3767e Use the new SQLite3::Database#busy_handler_timeout= method for a non-GVL-blocking, fair retry interval busy handler implementation
Co-Authored-By: Jean Boussier <byroot@ruby-lang.org>
2024-08-16 13:56:24 +02:00
Matthew Nguyen 41c547cb47 Translate SQLite3::BusyException into ActiveRecord::StatementTimeout 2024-08-16 13:22:44 +02:00
Tony Novak 2ea8e89fd1 Update PostgreSQLAdapter#extensions to include schema name
This allows the schema dumper's generated `enable_extension` statements
to include the schema name, if different from `current_schema`.

[Fix #52312]
2024-08-14 12:26:50 -04:00
Vasiliy Ermolovich eaa74eedba
EncryptedAttributeType#type should return cast_type's type. (#52247) 2024-08-13 14:04:24 -07:00
Nixon 90b1108a64 Bulk insert fixtures on SQLite 2024-08-11 04:05:44 -03:00
Tony Novak eb6d1709fe Allow disable_extension to be called with schema-qualified name
Note that the PostgreSQL DROP EXTENSION statement does not accept a
schema name (see https://www.postgresql.org/docs/current/sql-dropextension.html).
Since we allow `enable_extension` to be called with a schema-qualified
name, this commit allows `disable_extension` to be similarly called with
a schema-qualified name, but the schema name is chopped off in the
generated SQL statement.
2024-08-06 11:48:44 -04:00
Tony Novak e800fc683d Make create_schema / drop_schema reversible in migrations 2024-08-02 14:37:23 +02:00
fatkodima fd52a754f2 Support batching using custom columns 2024-07-27 11:55:52 +03:00
John Hawthorn 3b6af165df Revert "Merge pull request #51987 from fatkodima/exists-and-loaded2"
This reverts commit c9075e3643, reversing
changes made to a14eb2dc84.
2024-07-26 13:23:55 -07:00
Stephen Margheim 1e2c9048c4 Use SQLite `IMMEDIATE` transactions when possible.
Transactions run against the SQLite3 adapter default to IMMEDIATE mode to
improve concurrency support and avoid busy exceptions.

Fixture transactions use DEFERRED mode transactions as all `joinable`
transactions become DEFERRED transactions.
2024-07-26 09:02:08 +02:00
Hana Harencarova 0bdf44d921 Raise specific exception when a connection is not defined
Co-authored-by: Matthew Draper <matthewd@github.com>
2024-07-16 19:53:46 +00:00
Xavier Noria 32c5a358bb Delete the deprecated constant ActiveRecord::ImmutableRelation 2024-07-13 12:51:40 +02:00
Joshua Young 154f4a4ba9 [Fix 48688] Duplicate callback execution when child autosaves parent with has_one and belongs_to 2024-07-07 11:03:45 +05:30
heka1024 75421601ce Introduce `compressor` option to `ActiveRecord::Encryption::Encryptor` 2024-07-03 18:48:07 +09:00
Hartley McGuire 5c8172554f
Add condensed #inspect for Pool, Adapter, Config
Previously, it was very easy to accidentally leak a database password in
production logs if an error ends up calling inspect on a ConnectionPool
or an individual connection (Adapter). This is due to the default
`#inspect` output for Pools and Adapters being unnecessarily large, and
both currently including passwords (through the DatabaseConfig of a
Pool, and the internal configuration of an Adapter).

This commit addresses these issues by defining a custom `#inspect` for
ConnectionPool, AbstractAdapter, and DatabaseConfig. The condensed
`#inspect` only includes a few valuable fields instead of all of the
internals, which prevents both the large output and passwords from being
included.
2024-06-21 21:23:04 +00:00
Nony Dutton 77cf5e6d92 Add `.shard_keys` & `.connected_to_all_shards`
Currently, there is no (simple) way to ask a model if it connects to a
single database or to multiple shards. Furthermore, without looping
through a model's connections, I don't believe there's an easy way to
return a list of shards a model can connect to.

This commit adds a `@shard_keys` ivar that's set whenever `.connects_to`
is called. It sets the ivar to the result of `shards.keys`. `shards` in
`.connects_to` defaults to an empty hash and therefore when calling
`connects_to database: {...}` `@shard_keys` will be set to an empty array.

`@shard_keys` is set _before_ the following lines:

```
if shards.empty?
  shards[:default] = database
end
```

This conditional sets the one and only shard (`:default`) to the value of `database`
that we pass to `.connects_to`. This allows for calling
`connected_to(shard: :default)` on models configured to only connect to
a database e.g.:

```ruby
class UnshardedBase < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :primary }
end

class UnshardedModel < UnshardedBase
end

UnshardedBase.connected_to(shard: :default) {
UnshardedBase.connection_pool.db_config.name } => primary
```

This is ultimately still an _unsharded_ model which is why `@shard_keys`
gets set before the conditional.

With the new `@shard_keys` ivar we need a way for descendants of the
abstract AR model to return that same value. For that we leverage the
existing `.connection_class_for_self` method. That method returns the
ancestor of the model where `.connects_to` was called, or returns self if
it's the connection class:

```ruby
class UnshardedBase < ActiveRecord::Base
  self.abstract_class = true

  connects_to database: { writing: :primary }
end

class UnshardedModel < UnshardedBase
end

ActiveRecord::Base.connection_class_for_self => ActiveRecord::Base

UnshardedBase.connection_class_for_self => UnshardedBase(abstract)

UnshardedModel.connection_class_for_self => UnshardedBase(abstract)
```

The new `.shard_keys` method is a getter which returns the value of
`@shard_keys` from the connection class or it returns an empty array.
The empty array is necessary in cases where `connects_to` was never
called.

Finally, I've added an `.connected_to_all_shards` method which takes all of the
arguments for `.connected_to` except for `shard`. Instead, it loops through
every shard key and then delegates everything else to `.connected_to`. I've
used `.map` instead of `.each` so that we can collect the results of each block.
2024-06-17 19:54:25 +02:00
fatkodima 9e85d04e2e Optimize `ActiveRecord::Relation#exists?` with no conditions for loaded relations 2024-06-14 13:49:11 +02:00
Igor Depolli 00f38563a4
[ActiveRecord] Add option `filter` on `in_order_of` (#51761)
* Add option  on

* Add CHANGELOG and fix method doc

* Rename option to 'filter' and fix grammar

* Adjust filter attribute

* Fix typo and solve conflict

* Update activerecord/test/cases/relation/field_ordered_values_test.rb

Co-authored-by: Timo Schilling <timo@schilling.io>

---------

Co-authored-by: Timo Schilling <timo@schilling.io>
Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
2024-06-12 15:14:06 -07:00
Jay Ang 3e371c6dd6 Fix issue with IDs reader on preloaded associations for composite primary keys 2024-06-04 22:13:05 +08:00
Garen J. Torikian 5ff9915db9
Allow one to set `strict_loading_mode` globally 2024-06-02 14:38:38 -05:00
Carlos Antonio da Silva e12ba4d539 Fix method reference in Active Record changelog [ci skip] 2024-05-29 13:52:16 -03:00
Theodor Tonum d28e7c29a2 Add `ActiveRecord::Relation#readonly?`
Indicates whether a relation was marked readonly.
2024-05-27 21:51:04 +02:00
Mike Dalessio 2bf7e25243
Raise a descriptive error when a store column is misconfigured
If a developer has neglected to use a structured column type (hstore
or json) or to declare a serializer with `ActiveRecord.store`:

```ruby
  class User < ActiveRecord::Base
    store_accessor :settings, :notifications
  end
```

then a `ConfigurationError` will now be raised with a descriptive
error message when the accessor is read or written:

```ruby
  puts user.notifications
  # ActiveRecord::ConfigurationError: the column 'settings' has not
  # been configured as a store.  Please make sure the column is
  # declared serializable via 'ActiveRecord.store' or, if your
  # database supports it, use a structured column type like hstore or
  # json.
```

Previously, in this situation, a `NoMethodError` was raised when the
accessor was read or written:

```ruby
  puts user.notifications
  # NoMethodError: undefined method `accessor' for an instance of ActiveRecord::Type::Text
```

Raising a descriptive exception should help developers understand more
quickly what's wrong and how to fix it.

Closes #51699
2024-05-23 15:59:56 -04:00
Joshua Young 0516eafda2 [Fix #51720] Infer association klass as top level if model has same demodularized name 2024-05-23 08:04:57 +09:00
eileencodes 227c590d02
Add test and fix changelog for `schema_cache_ignored_table?` 2024-05-21 15:37:38 -04:00
eileencodes e815c6663a
Make public method for `schema_cache_ignored_tables?`
Previously we only provided a method to set the ignored schema cache
tables, but there was no way to ask if a table was ignored by the schema
cache. Applications may want to implement their own schema cache, or at
least run this check. Rather than forcing them to implement an internal
method, this adds a way to ask whether a table is ignored by the schema
cache code.

Usage:

```ruby
ActiveRecord.schema_cache_ignored_tables = ["developers"]
ActiveRecord.schema_cache_ignored_tables?("developers")
```
2024-05-21 14:42:25 -04:00
Rafael Mendonça França 52b417bca6
This will be released in 7.2, not 8 2024-05-14 18:05:40 +00:00
fatkodima 94af7c181a Change `BatchEnumerator#destroy_all` to return the total number of affected rows 2024-05-13 22:54:25 +03:00
Rafael Mendonça França bf59d363fb
Clean CHANGELOG for 8.0 2024-05-13 16:55:52 +00:00
Rafael Mendonça França 37fd0e7fe4
Development of Rails 8.0 starts now
🎉
2024-05-13 16:45:20 +00:00
fatkodima e057037c72 Support `touch_all` in batches 2024-05-13 09:23:57 +09:00
Sampat Badhe a44fbb11a3
Correct typo in activerecord changelog [ci skip]
Correct typo in activerecord changelog for -https://github.com/rails/rails/pull/50662
2024-05-12 10:43:00 +05:30
fatkodima 47f25b268a Add support for `:if_not_exists` and `:force` options to `create_schema` 2024-05-11 16:40:20 +03:00
lulalala 0a36c36dd8 Add index_errors: :nested_attributes_order mode
which respects reject_if and is in nested_attributes order.

When in default index_errors:true mode,
fix #24390 and return index based on full association order.
2024-05-09 20:03:53 +08:00
Nikita Vasilevsky 9cadf61835
Warn about changing `query_constraints:` behavior
This commit adds a deprecation warning for the `query_constraints:`
association option. This option will change behavior in the future versions
of Rails and applications are encouraged to switch to `foreign_key:` to preserve the
current behavior.
2024-05-08 20:08:09 +00:00
David Heinemeier Hansson e8e077dd16
Add ENV["SKIP_TEST_DATABASE_TRUNCATE"] flag to speed up multi-process test runs (#51686) 2024-05-06 17:04:01 -07:00
nisusam e0b7136b3e Fix typo from Changelog [ci skip] 2024-05-02 17:23:21 +05:30
Claire fc26e44181 Add support for recursive CTE in Active Record
```ruby
Post.with_recursive(
  post_and_replies: [
    Post.where(id: 42),
    Post.joins('JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id'),
  ]
)
```

Generates the following SQL:

```sql
WITH RECURSIVE "post_and_replies" AS (
  (SELECT "posts".* FROM "posts" WHERE "posts"."id" = 42)
  UNION ALL
  (SELECT "posts".* FROM "posts" JOIN post_and_replies ON posts.in_reply_to_id = post_and_replies.id)
)
SELECT "posts".* FROM "posts"
```
2024-05-02 12:32:27 +02:00
Cody Cutrer 5c5e8d2fd6 Pass validate(_check)_constraint through change_table 2024-05-01 15:33:37 -06:00
Joé Dupuis 2c88c80fc7
Add a Date decoder to the pg adapter to type cast dates
at the connection level

Fix #51448

Type cast columns of type `date` to ruby `Date` when running a raw
query through `ActiveRecord::Base.connection.select_all`.
2024-04-29 19:16:18 -07:00
Reid Lynch 715276071f
Strict loading using `:n_plus_one_only` does not eagerly load child associations.
Before:

    ```ruby
    person = Person.find(1)
    person.strict_loading!(mode: :n_plus_one_only)
    person.posts.first
    # SELECT * FROM posts WHERE person_id = 1; -- non-deterministic order
    ```

    After:

    ```ruby
    person = Person.find(1)
    person.strict_loading!(mode: :n_plus_one_only)
    person.posts.first # this is 1+1, not N+1
    # SELECT * FROM posts WHERE person_id = 1 ORDER BY id LIMIT 1;
    ```

    Strict loading in `:n_plus_one_only` mode is designed to prevent performance issues when
    deeply traversing associations. It allows `Person.find(1).posts`, but _not_
    `Person.find(1).posts.map(&:category)`. With this change, child associations are no
    longer eagerly loaded, to match intended behavior and to prevent non-deterministic
    order issues caused by calling methods like `first` or `last`.
    Fixes #49473.
2024-04-19 00:05:13 +00:00