I'm working on an enhancement to query constraints that will require me
to know when we have query constraints but not a composite key.
Currently if you have a composite key it will be included in the query
constraints list. There's not a way to differentiate between the two
which means that we're forced into setting the query constraints on the
associations for the primary key.
This change adds a `has_query_constraints?` method so we can check the
class for query constraints. The options still work as well but we can
be sure we're always picking up the query constraints when they're
present.
This `#use_puma?` check was [introduced][1] because Rails could
potentially display the wrong server URL in development if another host
or port is configured in `config/puma.rb`.
However, in Rack 3 the the name of the server class changed from
`Rack::Handler::Puma` to `Rackup::Handler::Puma`, which means that the
served_url is being logged again.
This commit fixes the check to accept either version of the class.
Additionally, puma was updated in Gemfile.lock because Puma 6.0.x prints
a deprecation warning about Rack::Handler that's fixed in 6.1.0.
[1]: 29648ff60e
Follow-up to #47178.
RDoc's Markdown parser requires multi-line list items to use a hanging
indent of at least four spaces. Otherwise, trailing lines will be
rendered as an independent paragraph, and the next list item will start
a new list.
We originally implemented this project to use OR queries instead of IN
because it seemed like there was no way to do that without a row
constructor. While working on implementing this feature in our vitess
gem I noticed that we can actually get the queries we wanted, and the
new code is more performant than generating an OR.
SQL Before:
```sql
SELECT "sharded_comments".*
FROM "sharded_comments"
WHERE ("sharded_comments"."blog_id" = 969142904
AND ("sharded_comments"."blog_post_id" = 357271355
OR "sharded_comments"."blog_post_id" = 756811794)
OR "sharded_comments"."blog_id" = 308674288
AND "sharded_comments"."blog_post_id" = 1055755181)
```
SQL After:
```sql
SELECT "sharded_comments".*
FROM "sharded_comments"
WHERE "sharded_comments"."blog_id"
IN (969142904, 308674288)
AND "sharded_comments"."blog_post_id"
IN (357271355, 756811794, 1055755181)
```
Using one of the tests that utilizes this code path, I benchmarked the
queries. The new implementation is faster:
Before:
```
Warming up --------------------------------------
queries 147.000 i/100ms
Calculating -------------------------------------
queries 1.486k (± 3.2%) i/s - 7.497k in 5.050742s
```
After:
```
Warming up --------------------------------------
queries 179.000 i/100ms
Calculating -------------------------------------
queries 1.747k (± 4.5%) i/s - 8.771k in 5.031424s
```
We can probably improve this more but I think this query is more in line
with what we want and expect while also being more performant (without
having to build a new row constructor in arel).
This adds additional coverage to ActionCable::Server to validate that
its output follow the Rack SPEC.
In addition to using Rack::CONTENT_TYPE for the Content-Type header,
there was another change required: the Content-Type header cannot be
specified when the Response status is 204, so the default health check
status was updated to 200
While these are valid Rack Handler names, their handler name is not the
same as their gem name.
| handler | gem |
| ------- | ---------- |
| fastcgi | fcgi |
| lsws | ruby-lsapi |
Because we're using a class_attribute to track all of the attribute_aliases,
each subclass was regenerating the parent class methods, causing some unexpected
deprecation messages.
Instead, we can use a class instance variable to track the attributes aliased locally
in that particular subclass. We then walk up the chain and re-define the attribute methods
if they haven't been defined yet.
The current example test for jobs using `perform_now` to run the job inline. This is problematic for jobs that have retries configured, as any exception that is retried will be silently rescued. Ideally, the test will still fail because the job did not perform the work it was supposed to, but it makes finding the root cause a lot harder.
Testing with `perform_enqueued_jobs` and `perform_later` gets around this problem, as the retries are also performed immediately and, assuming that the exception happens consistently, it will bubble up after exhausting its retries.
Therefore, this PR updates the basic test guidance to suggest `perform_enqueued_jobs` and `perform_later` over `perform_now`.
Both described behaviours make it harder to test that a job raises a specific exception, so this requires special handling, which I added a paragraph on. I can pull that out to a separate PR if desired.
This adds additional test coverage to ShowExceptions, since one of the
possible responses it creates was not previously tested. Because of the
previous [addition][1] of Rack::Lint, this also demonstrates that the
Content-Type header needed to be fixed.
[1]: 339dda4a82
Followup: https://github.com/rails/rails/pull/48645
Some template engines such as `jbuilder` use these Action View primitives
with types other than strings, which breaks a bunch of assumptions.
I wish I could add a test for this, but this is deep in private methods
I don't see a way to cover this.
Durations that were round-tripped through ActiveJob::Arguments.serialize
would appear fine at a first glance, but trying to perform
duration-math on them would fail:
```
irb(main):001:0> d = ActiveJob::Arguments.deserialize(ActiveJob::Arguments.serialize([1.year]))[0]
=> 1 year
irb(main):002:0> d + 1.day
activesupport-6.1.4.4/lib/active_support/duration.rb:242:in `+': undefined method `merge' for [[:years, 1]]:Array (NoMethodError)
```
Pluses cannot be used to create code blocks when the content includes a
space.
Found using a regular expression:
```bash
$ rg '#\s[^+]*\+[^+]*\s[^+]*\S\+'
```
We cannot compare paths directly to strings or that might fail on
different operating system. In this case, comparing to `/` fails on
Windows and we end up in endless recursion. We need to use
`Pathname#root?` to check if we reached the root of the folder structure