- ### Problem
ActionPack requires "action_view/base" at boot time, this
causes a variety of issue that I described in detail in #38024.
There is no real reason to require av/base in the
ActionDispatch::Debugexceptions class.
### Solution
Like any other components (such as ActiveRecord, ActiveJob...),
ActionView::Base shouldn't be loaded at boot time.
Here are the two main changes needed for this:
1) Actionview has a special initializer that needs to run
before the app is fully booted (adding a executor needs to be done
before application is done booting)
63ec70e700/actionview/lib/action_view/railtie.rb (L81-L84)
That initializer used a lazy load hooks but we can't do that anymore
because Action::Base view won't be triggered during booting process.
When it will get triggered, (presumably on the first request),
it's too late to add an executor.
------------------------------------------------
2) Compare to other components, ActionView doesn't use `Base` for
configuration flag. A lot of flags ares instead set on modules
(FormHelper, FormTagHelper).
The problem is that those module depends on AV::Base to be
loaded, as otherwise configuration set by the user aren't applied.
(Since the lazy load hooks hasn't been triggered)
63ec70e700/actionview/lib/action_view/railtie.rb (L66-L69)
We shouldn't wait for AB::Base to be loaded in order to set these
configuration. However, we need to do it inside an
`after_initialize` block in order to let application
set it to the value they want.
Closes#28538
Co-authored-by: betesh <iybetesh@gmail.com>"
The issue was reported in #29537. We expect Exception#annoted_source_code
to return an `Array`, but this contract may not be followed by all the
implementers.
Fixes#29537.
Enabling `SameSite` cookie protection is an addition to CSRF protection,
where cookies won't be sent by browsers in cross-site POST requests when set to `:lax`.
`:strict` disables cookies being sent in cross-site GET or POST requests.
Passing `:none` disables this protection and is the same as previous versions albeit a `; SameSite=None` is appended to the cookie.
See upgrade instructions in config/initializers/new_framework_defaults_6_1.rb.
More info [here](https://tools.ietf.org/html/draft-west-first-party-cookies-07)
_NB: Technically already possible as Rack supports SameSite protection, this is to ensure it's applied to all cookies_
This adds a regression test that previously failed checking controllers
don't have multiple ancestors which include url_helpers or path_helpers.
This is checked by digging through the ancestors and seeing if they
include either the url_helpers_module or path_helpers_module and making
sure only one ancestor does that.
We usually don't test performance changes (and also would not prefer to
test implementation this closely), but because this has regressed in the
past, and I think it would be relatively easy to accidentally introduce
again, I think we should test this one.
Previously, every time this was called it would return a new module.
Every time a new controller is built, it had one of these module
included onto it (see AbstractController::Railties::RoutesHelper).
Because each time this was a new module we would end up with a different
copy being included on each controller. This would also include a
different copy on a controller than on its superclass (ex.
ApplicationController). Furthermore, each generated module also extended
the url helper modules.
+--------------+ +-------------+
| | | |
| path_helpers | | url_helpers | (named routes added here)
| | | |
+------+----+--+ +----+--+-----+
^ ^ ^ ^
| | | |
| +---------------+ |
| | | |
| | +-----------+ |
| | | |
+------+--+---+ +--+----+-----+
| | | |
| (singleton) +------+ url_helpers | (duplicated for each controller)
| | | |
+-------------+ +-----+-------+
^
|
|
+---------+-------+
| |
| UsersController |
| |
+-----------------+
The result of this is that when named routes were added to the two
top-level modules, defining those methods became extremely slow because
Ruby has to invalidate the class method caches on all of the generated
modules as well as each controller. Furthermore because there were
multiple paths up the inheritance chain (ex. one through
UsersController's generated module and one through
ApplicationController's genereated module) it would end up invaliding
the classes multiple times (ideally Ruby would be smarter about this,
but it's much easier to solve in Rails).
Caching this module means that all controllers should include the same
module and defining these named routes should be 3-4x faster.
This method can generate two different modules, based on whether
supports_path is truthy, so those are cached separately.
After performing a request on a Metal controller the
controller instance on the integration session becomes
an instance of that Metal controller.
The next call to a named route that requires url_options
will throw a NoMethodError because a Metal controller
does not respond to url_options.
This changes the url_options method on the integration
session to check for the url_options method before
attempting to call it.
In https://github.com/rails/rails/pull/36388,
we supported passing objects that `respond_to` `render_in`
to `render`, but _only_ in views.
This change does the same for controllers, as Rails
generally gives the expectation that `render` behaves
the same in both contexts.
Co-authored-by: Aaron Patterson <tenderlove@github.com>
= 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>
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.
`MonitorMixin` setup internal variables in `initialize`, so need to call
that before use.
`ActionController::Live::Buffer` only use methods that do not depend on those
internal variables, so works expertly.
But since Ruby 2.7, methods that were not originally the case also depend on
internal variables. As a result, some tests fail in Ruby 2.7.
https://buildkite.com/rails/rails/builds/65193#02e136eb-edea-4367-aee0-77e0a82f8531/990-1200
I'm not sure if this should be considered Ruby incompatible, but I fixed
this because its usage is wrong.
Related to [Feature #16255: Make `monitor.rb` built-in](https://bugs.ruby-lang.org/issues/16255)
- `respond_to any` doesn't allow to specify a content type and
the content type in the response will be based on the request
format.
```ruby
def my_action
respond_to do |format|
format.html { render(html: 'hello') }
format.any { render(json: { foo: 'bar'}) }
end
end
get('my_action.csv')
# Before this patch, content type was `text/csv'
# Ather this patch, content type is correctly set to whateve we did in the `format.any` block
```
If the client specify the type of data he wants but the server
doesn't know how to handle it and return plain text (or whatever)
I don't think it make sense to falsey claim that we are returning
a `text/csv` a response where in fact we are returning something else.
Fix#37345
This commit adds a test to ensure the behavior of inline `around_action`
calls, as well as a change to the guides to call out this alternate use of
`around_action`.
Closes#37616
When a test method name includes a slash (e.g. `test "signup on the
/signup page"`) the screenshot is generated in the nested directory on
systems that use slash as a directory separator (e.g. a screenshot
called `signup_page.png` is generated within `failures_signup_on_the_`).
Nesting screenshots causes an issue with `tmp:clear` rake task:
```
== Removing old logs and tempfiles ==
rails aborted!
Errno::EISDIR: Is a directory @ apply2files - tmp/screenshots/failures_signup_on_the_
/var/lib/gems/2.5.0/gems/railties-5.2.3/lib/rails/tasks/tmp.rake:41:in `block (3 levels) in <top (required)>'
/var/lib/gems/2.5.0/gems/railties-5.2.3/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
...
Tasks: TOP => tmp:clear => tmp:screenshots:clear
```
While the error could be prevented by changing `tmp:clear` task, there's
no reason to generate deep directory structures for tests using slashes.
To prevent a similar problem on Windows, we'll also "sanitize"
backslashes.
Replacing the problamatic characters with dashes seems to be a safe
workaround, although dash is very arbitrary choice in this case.
Co-Authored-By: Louis-Michel Couture <louim_1@hotmail.com>
The concept of treating Accept header lists including "*/*" as
identifying the request as coming from a browser, and allowing the mime
negotiation to fall back to a HTML response, was introduced in commits
1310231c15 and dc5300adb6.
I am adding the comment (based on the commit messages of the two commits
mentioned) because it is far from obvious why this regex exists and what
it does.
Co-authored-by: Matthew Riddle <mriddle89@gmail.com>
* Support the OPTIONS Http Verb
ActionDispatch::Integration::Session#process already lists OPTIONS as a valid verb symbol to pass
* Update actionpack/lib/action_dispatch/testing/integration.rb
It fixes the problem in propagating return_only_media_type_on_content_type
and fixes the corresponding test being ineffective.
The mentioned test addes the following line:
...config.action_dispatch.return_only_media_type_on_content_type = true
to the config and checks if it takes effect. However, in this scenario,
the value is already true before this line.
Moreover, the users are supposed to flip this from true to false in real
situations.
This commit flips the config in the test, making it to fail as
expected. The next commit will fix the failure.
In order for return_only_media_type_on_content_type to appropriately
take effect on ActionDispatch::Response, we want to know when
ActionDispatch::Response is loaded.
As load hooks for ActionDispatch would be too broad, the appropriate
registry is for ActionDispatch::Response itself.
Looking into other examples, a hook name is a full class name in
snake case with `_base` suffix omitted, if any. Therefore, in this case,
:action_dispatch_response seems appropriate.
Similar to b744372f2d, this defers loading
`ActionDispatch::Response` until after initialization, which will allow
applications to boot a bit faster in development but also paves the way
for `return_only_media_type_on_content_type` to work correctly when set
from `new_framework_defaults_6_0.rb`.
Benchmark:
$ cat test.rb
require "bundler/setup"
before = ObjectSpace.each_object(Module).count
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
require "action_controller"
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
after = ObjectSpace.each_object(Module).count
puts "took #{finish - start} and created #{after - before} modules"
Before:
$ ruby test.rb
took 0.35654300000169314 and created 608 modules
After:
$ ruby test.rb
took 0.2770050000108313 and created 466 modules
Co-authored-by: Serena Fritsch <serena@intercom.io>
Before this patch each named routes generates two UrlHelper instances.
Both are almost identical, their only difference is the `url_strategy`
property.
This patch get rid of that property and instead pass it as an argument
to call, so effectively it's stored in the closure.