Commit Graph

92162 Commits

Author SHA1 Message Date
Petrik
8b173d9551 Remove "Migrating from Classic to Zeitwerk" guide [ci-skip]
Rails 7 apps require running in `zeitwerk` mode, so we no longer need
the migration guide. The "Autoloading and Reloading Constants" guide
also handles autoloading with Zeitwerk, including `autoload_paths`, the
`zeitwerk:check` command and more.
2024-06-19 15:27:17 +02:00
Jean Boussier
362fbd2a7f
Merge pull request #52151 from fatkodima/exists-with-updated-records
Fix `ActiveRecord::Relation#exists?` with no conditions for loaded relations and updated records
2024-06-19 15:12:31 +02:00
Petrik
b06c2c7da0 Move performance section under "Digging Deeper" [ci-skip]
This section was moved to "Advanced Active Record" in
35ad43b1a5b8eaed48588c8045 by accident.
2024-06-19 15:08:47 +02:00
Ridhwana
168b2b369c
[RF-DOCS] Active Record Migration Documentation (#51928)
- [x] We talk about transactions and how to disable them early on, as part of the first few paragraphs, that could be a subsection to add separation.
- [x] The guide goes into reversible early, before even talking about generating migrations and other basic stuff, and then later talks more about it. I think it's important to lay the foundation of change vs up/down, and the fact that migrations should always try to be able to be rolled back, but maybe we can do that without going into reversible that early in the guide, which complicates things further.
- [x] We mention bin/rails generate --help to look for more details, but we could mention specific generators also offer help too, e.g. bin/rails generate model --help or bin/rails generate migration --help
- [x] There's a small section about composite PKs, but there's also [a whole guide on it](https://edgeguides.rubyonrails.org/active_record_composite_primary_keys.html), we can add a link to it from the migrations guide at least for more info on the topic.
- [x] The section that talks about execute shows an example of a specific model Product.connection.execute, but we can call execute directly within a migration, that might be simpler to show.
- [x] We talk about "seed data " in setup & preparing sections, but never mention it before, or explain what seed data is. There's a section about seed data later in the guide, perhaps we can link to it to facilitate.
- [x] In "running specific migrations", bin/rails db:migrate VERSION=zomg actually raises a different error: Invalid format of target version: `VERSION=zomg`... might need a different example there for the unknown migration version error. (no need to show this invalid format one)
- [x] The section about referential integrity can likely be better explained, in particular I think it's worth mentioning that even though the "AR method/way" (the pattern, I mean) doesn't think such "intelligence" belongs to the database, foreign keys and unique indexes are generally safer at the database level. (and should likely have their counterparts explicitly added in code with associations and validations). I just don't want to convey that someone shouldn't be adding FKs & unique constraints, because not adding these can definitely bite you.

Other changes: 
- [x] Moved sections around 
- [x] Added a section about "Rails Migration Version Control"
- [x] Added a section about "Using UUIDs instead of IDs for Primary Keys"

Co-authored-by: bhumi1102 <bhumi1102@gmail.com>
Co-authored-by: Bartosz Łęcki <bart.lecki@gmail.com>
Co-authored-by: Cecile Veneziani <cveneziani@users.noreply.github.com>
Co-authored-by: hatsu <hajiwata0308@gmail.com>
Co-authored-by: Petrik de Heus <petrik@deheus.net>
Co-authored-by: Ahmad hamza  <ahmad.hamza@toptal.com>
Co-authored-by:  Bart de Water <496367+bdewater@users.noreply.github.com>
Co-authored-by: Amanda Perino <58528404+AmandaPerino@users.noreply.github.com>
Co-authored-by: Andy Atkinson <andyatkinson@gmail.com>
Co-authored-by: Jamie Gaskins <jgaskins@gmail.com>
2024-06-19 13:06:58 +02:00
fatkodima
5dd2da7ee8 Fix ActiveRecord::Relation#exists? with no conditions for loaded relations and updated records 2024-06-19 12:15:20 +03:00
Jean Boussier
869c7bf094 Improve BacktraceCleaner code example [ci-skip]
With newer rubies, removing a prefix is much simpler.
2024-06-19 09:16:30 +02:00
Eileen M. Uchitelle
ff0ef93e28
Merge pull request #51009 from HeyNonster/nony--add-on-all-shards
Add `.shard_keys`, `.sharded?`, & `.connected_to_all_shards` methods to AR Models
2024-06-18 05:45:23 -07:00
Xavier Noria
43e2281da8
Merge pull request #52147 from rails/fxn/ar-transaction-docs
Iterate the docs of ActiveRecord::Transaction
2024-06-18 13:34:54 +02:00
Xavier Noria
0ec6f23197
Update activerecord/lib/active_record/transaction.rb
Co-authored-by: Jean byroot Boussier <jean.boussier+github@shopify.com>
2024-06-18 13:02:32 +02:00
Xavier Noria
f8ee9ebb66 Iterate the docs of ActiveRecord::Transaction 2024-06-18 13:01:55 +02:00
Jean Boussier
9ccbab1658
Merge pull request #52145 from Shopify/alias-attribute-override-inherited-methods
Fix `alias_attribute` to ignore methods defined in parent classes
2024-06-18 10:04:11 +02:00
Jean Boussier
403743ed88 Fix alias_attribute to ignore methods defined in parent classes
Fix: https://github.com/rails/rails/issues/52144

When defining regular attributes, inherited methods aren't overriden,
however when defining aliased attributes, inherited methods aren't
considered.

This behavior could be debatted, but that was the behavior prior
to https://github.com/rails/rails/pull/52118, so I'm restoring it.
2024-06-18 09:44:31 +02:00
Yasuo Honda
98636b3a78
Merge pull request #52141 from MaxLap/fix_log_causes_ruby_head
Fixes tests with nested exception backtraces on Ruby master
2024-06-18 08:19:37 +09: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
Aaron Patterson
6d126e03db
Merge pull request #51288 from JoeDupuis/stop-caching-on-failure-activestorage-proxy-controller
Expire caching when a download fail while proxying in ActiveStorage
2024-06-17 10:35:42 -07:00
Joé Dupuis
f7ecde8331
Expire caching when a download fail while proxying in ActiveStorage
Fix #51284

Both Proxy controllers in Active Storage set the caching headers early
before streaming.

In some instances (see #51284), it is possible for the file
download (from the service to server) to fail before we send the first
byte to the client (response not yet committed).

In those instances, this change would invalidate the cache and return
a better response status before closing the stream.
2024-06-17 09:49:11 -07:00
Maxime Lapointe
3e816bfe72 Fixes tests with nested exception backtraces on Ruby master
Ruby master did the following changes (and probably more)
https://bugs.ruby-lang.org/issues/16495
https://bugs.ruby-lang.org/issues/20275
2024-06-17 09:43:28 -04:00
Jean Boussier
5ef7f73c30
Merge pull request #52131 from fatkodima/remove-unneeded-with_connection
Fix more `with_connection` offences inside Active Record
2024-06-17 08:07:15 +02:00
Petrik de Heus
445de23b21
Merge pull request #51533 from p8/guides/advanced-active-record
Move "Advanced Active Record" guides to separate section [ci-skip]
2024-06-16 16:31:09 +02:00
fatkodima
ae62d08e92 Fix more with_connection offences inside Active Record 2024-06-16 11:36:09 +03:00
Xavier Noria
23729cec4e
Merge pull request #52130 from rails/fxn/trx-transaction-guide
Document test transactions w/ multiple databases
2024-06-15 13:55:36 +02:00
Xavier Noria
ec056dd8fb Document test transactions w/ multiple databases 2024-06-15 13:44:59 +02:00
Rafael Mendonça França
3342f13d12
Move the rewind code closer to the reason why we need to rewind
We only need to rewind because we call `read_body_stream`. Since
that method is only called in one place, move the rewing to inside it.
2024-06-14 18:56:36 +00:00
Jean Boussier
c9075e3643
Merge pull request #51987 from fatkodima/exists-and-loaded2
Optimize `ActiveRecord::Relation#exists?` with no conditions for loaded relations
2024-06-14 14:12:42 +02:00
fatkodima
9e85d04e2e Optimize ActiveRecord::Relation#exists? with no conditions for loaded relations 2024-06-14 13:49:11 +02:00
Sean Doyle
5fa61101c9 Mention yield :head in Guides
Follow up to [#50527][]

Highlight the presence of the `yield :head` pattern established by
`turbo-rails` and adopted by Rails as part of [#50527][].

New applications will generate their application layout with `yield
:head`, so mention that in the documentation.

Also include the `yield :head` call in generated plugin layouts.

[#50527]: https://github.com/rails/rails/pull/50527
2024-06-14 11:16:39 +02:00
Xavier Noria
a14eb2dc84
Merge pull request #52124 from rails/fxn/transactions-test-guide
Document transactions in the testing guide
2024-06-14 10:48:14 +02:00
Xavier Noria
a1f523bc47 Document transactions in the testing guide 2024-06-14 10:47:56 +02:00
Yasuo Honda
5a828e9ebf
Merge pull request #52123 from yahonda/bump_stringio_311
Bump stringio to 3.1.1
2024-06-14 08:51:39 +09:00
Yasuo Honda
e3a28aa3dc Bump stringio to 3.1.1
This commit addresses this CI failure:
https://buildkite.com/rails/rails/builds/108372#0190131e-ee1a-420b-8355-9eb08eb5c29a

* Without this commit
```ruby
$ ruby -v
ruby 3.2.4 (2024-04-23 revision af471c0e01) [x86_64-linux]
$ cd guides/bug_report_templates
$ ruby action_controller.rb
... snip ...
Installing rails 7.1.3.4
/home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/runtime.rb:304:in `check_for_activated_spec!': You have already activated stringio 3.1.0, but your Gemfile requires stringio 3.1.1. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/runtime.rb:25:in `block in setup'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/spec_set.rb:191:in `each'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/spec_set.rb:191:in `each'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/runtime.rb:24:in `map'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/runtime.rb:24:in `setup'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/inline.rb:66:in `block (2 levels) in gemfile'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/settings.rb:158:in `temporary'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/inline.rb:51:in `block in gemfile'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler.rb:403:in `block in with_unbundled_env'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler.rb:658:in `with_env'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler.rb:403:in `with_unbundled_env'
    from /home/yahonda/.rbenv/versions/3.2.4/lib/ruby/gems/3.2.0/gems/bundler-2.5.4/lib/bundler/inline.rb:42:in `gemfile'
    from action_controller.rb:5:in `<main>'
$
```
2024-06-14 08:24:47 +09:00
Jason Kim
9dcf17ec4c Add a config for preserving timezone information
when calling `to_time` on TimeWithZone object

Co-authored-by: jhawthorn <jhawthorn@github.com>
2024-06-13 14:56:40 -07:00
Rafael Mendonça França
f5355a21ae
Merge pull request #51219 from mylesboone/order_references_arel_attribute
[Fix #49999] properly reference from Arel::Attribute args
2024-06-13 15:40:46 -04:00
John Hawthorn
2627c953cb
Avoid using to_time in TimeWithZone#-
We're more likely to already have utc and can avoid constructing the
extra time object, and this will avoid deprecations on unconfigured
to_time_preserves_timezone.
2024-06-13 19:37:54 +00:00
Rafael Mendonça França
5cb2603d56
Merge pull request #52040 from zzak/re-52026
Rails::ConsoleMethods deprecation warning should point to the source
2024-06-13 15:25:35 -04:00
Rafael Mendonça França
638f645097
Merge pull request #52115 from deepakmahakale/notes-ui-changelog
Add changelog for the new internal route rails/info/notes [ci skip]
2024-06-13 13:22:29 -04:00
Rafael Mendonça França
02cefb2023
Merge pull request #52112 from y-yagi/fix_driven_by_for_devcontainer
Correctly output `driven_by` setting for Development Containers
2024-06-13 13:21:56 -04:00
Deepak Mahakale
306d99f8ca
Add changelog for the new internal route rails/info/notes 2024-06-13 17:14:37 +00:00
Jean Boussier
a2fb851526
Merge pull request #52118 from Shopify/fix-code-generator-bloat
Fix a performance regression in attribute methods
2024-06-13 17:59:50 +02:00
Rafael Mendonça França
3ec2f19417
Merge pull request #50305 from MaxLap/log_cause_trace_debug_exceptions
Log trace of causes for unhandled exceptions
2024-06-13 11:59:21 -04:00
Jean Boussier
514d474836 Fix a performance regression in attribute methods
Fix: #52111
Fix: 5dbc7b4

The above commit caused the size of the `CodeGenerator` method cache
to explode, because the dynamic namespace is way too granular.

But there is actually a much better fix for that, since `alias_attribute`
is now generating exactly the same code as the attribute it's aliasing,
we can generated it as the canonical method in the cache, and then just
define it in the model as the aliased name.

This prevent the cache from growing a lot, and even reduce memory
usage further as the original attribute and its alias now share
the same method cache.
2024-06-13 17:50:11 +02:00
Jean Boussier
4a4b399830
Merge pull request #52113 from Shopify/transaction-committed-open
`ActiveRecord::Transaction#open?` returns false if the transaction is finalized
2024-06-13 11:15:35 +02:00
Jean Boussier
884af53be2 ActiveRecord::Transaction#open? returns false if the transaction is finalized
Followup: https://github.com/rails/rails/pull/52104
2024-06-13 10:55:55 +02:00
Jean Boussier
1eb5761327
Merge pull request #52104 from Shopify/user-transaction-continued
Harden the `.current_transaction` API
2024-06-13 10:00:26 +02:00
Matthew Draper
fadb6830f8 Harden the .current_transaction API
Based on https://github.com/rails/rails/pull/52017

One concern raised by Xavier is users holding on the return value
of `.current_transaction` beyond the point where it is committed /
rolled back / invalidated.

I believe this is an invalid use of the API, just like holding
`ActiveRecord::Base.connection` beyond the scope of a request is.

However we can be more explicit about it, so I changed the callback
registration methods to raise an error when called on a finalized
transaction.

Another concern was the usability of the null-object in the Active
Record notification payloads, and I agree that while the null-object
make sense when calling `Model.current_transaction`, it doesn't make
sense to include it in the payload of events. The goal of the
`.current_transaction` API is to allow implementing transaction aware
code in a streamlined way. The goal of the `:transaction` in events
however it to allow logging whether a query was inside a transaction
or not, so it's much more ergonomic for it to be nilable.
So I kept Matthew's change that passes `transaction: nil` in `sql.active_record` events
when not inside a transaction. I also added test coverage to make
sure it behaves consistently whether we're inside a transactional
test or not.

I also kept the separation between internal and "user" transaction
objects, as I think it's a nice way to limit the effectively exposed
API, and prevent users from abusing that API too much.

Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
2024-06-13 09:34:58 +02:00
Yuji Yaginuma
8673f06852 Run system test on Devcontainer smoke test
To confirm the files for Dev Containers are generated correctly.
2024-06-13 16:31:10 +09:00
Yuji Yaginuma
44a64ce904 Correctly output driven_by setting for Development Containers
Currently, `ENV["SELENIUM_HOST"]` is evaluated when generating a file. So
the result was the following.

```
  driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ], options: {
    browser: :remote,
    url: "http://:4444"
  }
```

This PR fixes to output the URL setting just as a string. The after
result is the following.

```
  driven_by :selenium, using: :headless_chrome, screen_size: [ 1400, 1400 ], options: {
    browser: :remote,
    url: "http://#{ENV["SELENIUM_HOST"]}:4444"
  }
```
2024-06-13 16:30:20 +09:00
Myles Boone
e0c2363d9a properly reference tables from Arel in #order 2024-06-13 00:16:32 -04:00
Samuel Williams
ed68af0f62
Utilize Rack 3 streaming. 2024-06-13 10:27:09 +09:00
Maxime Lapointe
f47ef36c4d
Log trace of causes for unhandled exceptions 2024-06-12 22:51:15 +00:00
Rafael Mendonça França
827f4ef15c
Merge pull request #52059 from fatkodima/move-associations-errors-to-errors
Explicitly load Active Record associations related errors
2024-06-12 18:21:17 -04:00