| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
| |
The Mapper build_path method marks routes where path parameters are part
of a path segment as custom routes by altering the regular expression, e.g:
get '/foo-:bar', to: 'foo#bar'
There were some edge cases where certain constructs weren't being picked
up and this commit fixes those.
Fixes #23069.
|
|
|
|
|
|
|
|
|
| |
This reverts commit 5d1b7c3b441654e8008dcd303f5367883ec660a6.
The change here didn't actually fix the issue it was trying to fix, and
this isn't the correct way to fix either issue. The problem is switching
from the builder to grouping with find_all/regex is now very dependent
on how you structure your path pattern.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In commit d993cb3 `build_path` was changed from using `grep` to
`find_all` to save array allocations.
This change was a little too aggressive in that when the dash comes
before the symbol like `/omg-:song` the symbol is skipped.
Removing the check for `n.right.left.literal?` fixes this issue, but
does add back some allocations. The number of allocations are still well
less than before.
I've added a regression test to test this behavior for the future.
Fixes #23069.
Array allocations as of d993cb3:
```
{:T_SYMBOL=>11}
{:T_REGEXP=>17}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_OBJECT=>91009}
{:T_DATA=>100088}
{:T_HASH=>114013}
{:T_STRING=>159637}
{:T_ARRAY=>321056}
{:T_IMEMO=>351133}
```
Array allocations after this change:
```
{:T_SYMBOL=>11}
{:T_REGEXP=>1017}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_DATA=>84092}
{:T_OBJECT=>87009}
{:T_HASH=>110015}
{:T_STRING=>166152}
{:T_ARRAY=>322056}
{:T_NODE=>343558}
```
|
|
|
|
|
|
|
| |
- `CONTROLLER` argument can now be supplied in different ways (Rails::WelcomeController, Rails::Welcome, rails/welcome)
- If `CONTROLLER` argument was supplied but it does not exist, will warn the user that this controller does not exist
- If `CONTROLLER` argument was supplied and no routes could be found matching this filter, will warn the user that no routes were found matching the supplied filter
- If no routes were defined in the config/routes.rb file, will warn the user with the original message
|
|\
| |
| | |
Remove original root method from Base module and kept overridden implementation in Resources module.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- The root method is defined and documented in Base module and
decorated in Resources module.
- The documentation in Base module actually talks about method
signature of decorated method from Resources module.
- Argument handling was moved to decorated method in
https://github.com/rails/rails/commit/977455cc2efb94f40b4c0d46d1842be198ed7c4c
to handle options such as :as with directly passed path parameter.
- To avoid the confusion, removed original root method from Base module
and only kept overridden version in Resources module.
- References - https://github.com/rails/rails/pull/12208 &
https://github.com/rails/rails/pull/12208#issuecomment-24350897.
|
| |
| |
| |
| |
| |
| |
| |
| | |
- Earlier only Hash was allowed as params argument to url_helpers.
- Now ActionController::Parameters instances will also be allowed.
- If the params are not secured then it will raise an ArgumentError to
indicate that constructing URLs with non-secure params is not recommended.
- Fixes #22832.
|
|\ \
| | |
| | | |
Prevent ActionController::Parameters in url_for
|
| |/ |
|
|/ |
|
|\
| |
| | |
Add `Routing` namespace to point appropriate constant
|
| |
| |
| |
| | |
Make it clear we use `ActionDispatch::Routing::Endpoint`
|
|/
|
|
|
|
| |
* Integrate to raise `ArgumentError`
* Detailed error message when `path` is not defined
* Add a test case, invalid rack app is passed
|
|
|
|
|
| |
This code was added for migration from Rails 3.1 to upper,
now we are developing Rails 5.
|
|
|
| |
`Forwardable` has been used in the past
|
|
|
|
|
| |
When `require 'active_support/rails'`, 'active_support/deprecation'
is automatically loaded.
|
|\
| |
| | |
Change `Journey::Route#verb` to return string instead of regexp.
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
By [this commit](https://github.com/rails/rails/commit/0b476de445faf330c58255e2ec3eea0f3a7c1bfc)
`Journey::Route#verb` need not to return verb as regexp.
The returned value is used by inspector, so change it to be a string.
Add inspect_with_multiple_verbs test case to keep the behavior of
inspector correctly.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When an application has multiple root entries with different
constraints, the current solution is to use `get '/'`. Example:
**Currently I have to do:**
```ruby
get '/', to: 'portfolio#show', constraints: ->(req) { Hostname.portfolio_site?(req.host) }
get '/', to: 'blog#show', constraints: ->(req) { Hostname.blog_site?(req.host) }
root 'landing#show'
```
**But I would like to do:**
```ruby
root 'portfolio#show', constraints: ->(req) { Hostname.portfolio_site?(req.host) }
root 'blog#show', constraints: ->(req) { Hostname.blog_site?(req.host) }
root 'landing#show'
```
Other URL matchers such as `get`, `post`, etc, already allows this, so I
think it's fair that `root` also allow it since it's just a shortcut for
a `get` internally.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When generating the url for a mounted engine through its proxy, the path should be the sum of three parts:
1. Any `SCRIPT_NAME` request header or the value of `ActionDispatch::Routing::RouteSet#relative_url_root`.
2. A prefix (the engine's mounted path).
3. The path of the named route inside the engine.
Since commit https://github.com/rails/rails/commit/44ff0313c121f528a68b3bd21d6c7a96f313e3d3, this has been broken. Step 2 has been changed to:
2. A prefix (the value of `ActionDispatch::Routing::RouteSet#relative_url_root` + the engine's mounted path).
The value of `ActionDispatch::Routing::RouteSet#relative_url_root` is taken into account in step 1 of the route generation and should be ignored when generating the mounted engine's prefix in step 2.
This commit fixes the regression by having `ActionDispatch::Routing::RouteSet#url_for` check `options[:relative_url_root]` before falling back to `ActionDispatch::Routing::RouteSet#relative_url_root`. The prefix generating code then sets `options[:relative_url_root]` to an empty string. This empty string is used instead of `ActionDispatch::Routing::RouteSet#relative_url_root` and avoids the duplicate `relative_url_root` value in the final result.
This resolves #20920 and resolves #21459
|
|/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The `url_for` methods in `actionpack` and `actionview`
now make a copy of the provided options
before generating polymorphic paths or URLs.
The bug in the previous behavior
is most noticeable in a case like:
url_options = [:new, :post, param: 'value']
if current_page?(url_options)
css_class = "active"
end
link_to "New Post", url_options, class: css_class
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Controllers should always have a request and response when responding.
Since we make this The Rule(tm), then controllers don't need to be
somewhere in limbo between "asking a response object for a rack
response" or "I, myself contain a rack response". This duality leads to
conditionals spread through the codebase that we can delete:
* https://github.com/rails/rails/blob/85a78d9358aa728298cd020cdc842b55c16f9549/actionpack/lib/action_controller/metal.rb#L221-L223
|
|
|
|
| |
This saves a lambda and request allocation on each request.
|
|
|
|
|
| |
controllers should always go through the `action` class method so that
their middleware is respected.
|
|
|
|
|
| |
now the caller can just treat it like a regular controller even though
it will return a 404
|
|
|
|
|
| |
the dispatcher class isn't configurable anymore, so pull up allocation
to the method that needs it.
|
|
|
|
|
|
| |
Now that we don't have subclasses depending on this method (they augment
the request class instead of the dispatch class) we can remove this
method and directly ask the request object for the controller class
|
| |
|
|
|
|
| |
we don't need it anymore. We always use the same dispatcher in tests.
|
|
|
|
|
|
| |
controller class resolution has been moved to the request object, so we
should override that method instead of relying on the RouteSet to
generate the controller class.
|
| |
|
|
|
|
|
|
|
|
|
| |
Since none of the action pack tests failed without this conditional it
didn't seem necessary. This fixes the build because it correctly returns
a 404 instead of a 500 for the asset routes test.
Test that was failing was in the `assets_test.rb` file and was the test
named `test_assets_routes_are_not_drawn_when_compilation_is_disabled`.
|
|
|
|
|
|
|
|
|
|
| |
This refactoring moves the controller class name that was on the route
set to the request. The purpose of this refactoring is for changes we
need to move controller tests to integration tests, mainly being able to
access the controller on the request instead of having to go through
the router.
[Eileen M. Uchitelle & Aaron Patterson]
|
|
|
|
|
|
|
| |
`ActiveSupport::Dependencies.constantize(const_name)` calls
`Reference.new` which is defined as
`ActiveSupport::Dependencies.constantize(const_name)` meaning this call
is already cached and we're doing caching that isn't necessary.
|
|
|
|
| |
This way we can make the Route object a read-only data structure.
|
|
|
|
|
| |
nobody should be touching the routes hash without going through the
NamedRouteCollection object.
|
|
|
|
|
| |
We shouldn't be messing with the NamedRouteCollection internals. Just
ask the object if the named route is in there.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
```ruby
require 'action_pack'
require 'action_dispatch'
require 'benchmark/ips'
route_set = ActionDispatch::Routing::RouteSet.new
routes = ActionDispatch::Routing::Mapper.new route_set
ObjectSpace::AllocationTracer.setup(%i{path line type})
result = ObjectSpace::AllocationTracer.trace do
500.times do
routes.resources :foo
end
end
sorted = ObjectSpace::AllocationTracer.allocated_count_table.sort_by(&:last)
sorted.each do |k,v|
next if v == 0
p k => v
end
__END__
Before:
{:T_SYMBOL=>11}
{:T_REGEXP=>17}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_OBJECT=>99009}
{:T_DATA=>100088}
{:T_HASH=>122015}
{:T_STRING=>159637}
{:T_IMEMO=>363134}
{:T_ARRAY=>433056}
After:
{:T_SYMBOL=>11}
{:T_REGEXP=>17}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_OBJECT=>91009}
{:T_DATA=>100088}
{:T_HASH=>114013}
{:T_STRING=>159637}
{:T_ARRAY=>321056}
{:T_IMEMO=>351133}
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rather than building a regexp for every route, lets use the strategy
pattern to select among objects that can match HTTP verbs. This commit
introduces strategy objects for each verb that has a predicate method on
the request object like `get?`, `post?`, etc.
When we build the route object, look up the strategy for the verbs the
user specified. If we can't find it, fall back on string matching.
Using a strategy / null object pattern (the `All` VerbMatcher is our
"null" object in this case) we can:
1) Remove conditionals
2) Drop boot time allocations
2) Drop run time allocations
3) Improve runtime performance
Here is our boot time allocation benchmark:
```ruby
require 'action_pack'
require 'action_dispatch'
route_set = ActionDispatch::Routing::RouteSet.new
routes = ActionDispatch::Routing::Mapper.new route_set
result = ObjectSpace::AllocationTracer.trace do
500.times do
routes.resources :foo
end
end
sorted = ObjectSpace::AllocationTracer.allocated_count_table.sort_by(&:last)
sorted.each do |k,v|
next if v == 0
p k => v
end
__END__
Before:
$ be ruby -rallocation_tracer route_test.rb
{:T_SYMBOL=>11}
{:T_REGEXP=>4017}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_DATA=>84092}
{:T_OBJECT=>99009}
{:T_HASH=>122015}
{:T_STRING=>216652}
{:T_IMEMO=>355137}
{:T_ARRAY=>441057}
After:
$ be ruby -rallocation_tracer route_test.rb
{:T_SYMBOL=>11}
{:T_REGEXP=>17}
{:T_STRUCT=>6500}
{:T_MATCH=>12004}
{:T_DATA=>84092}
{:T_OBJECT=>99009}
{:T_HASH=>122015}
{:T_STRING=>172647}
{:T_IMEMO=>355136}
{:T_ARRAY=>433056}
```
This benchmark adds 500 resources. Each resource has 8 routes, so it
adds 4000 routes. You can see from the results that this patch
eliminates 4000 Regexp allocations, ~44000 String allocations, and ~8000
Array allocations. With that, we can figure out that the previous code
would allocate 1 regexp, 11 strings, and 2 arrays per route *more* than
this patch in order to handle verb matching.
Next lets look at runtime allocations:
```ruby
require 'action_pack'
require 'action_dispatch'
require 'benchmark/ips'
route_set = ActionDispatch::Routing::RouteSet.new
routes = ActionDispatch::Routing::Mapper.new route_set
routes.resources :foo
route = route_set.routes.first
request = ActionDispatch::Request.new("REQUEST_METHOD" => "GET")
result = ObjectSpace::AllocationTracer.trace do
500.times do
route.matches? request
end
end
sorted = ObjectSpace::AllocationTracer.allocated_count_table.sort_by(&:last)
sorted.each do |k,v|
next if v == 0
p k => v
end
__END__
Before:
$ be ruby -rallocation_tracer route_test.rb
{:T_MATCH=>500}
{:T_STRING=>501}
{:T_IMEMO=>1501}
After:
$ be ruby -rallocation_tracer route_test.rb
{:T_IMEMO=>1001}
```
This benchmark runs 500 calls against the `matches?` method on the route
object. We check this method in the case that there are two methods
that match the same path, but they are differentiated by the verb (or
other conditionals). For example `POST /users` vs `GET /users`, same
path, different action.
Previously, we were using regexps to match against the verb. You can
see that doing the regexp match would allocate 1 match object and 1
string object each time it was called. This patch eliminates those
allocations.
Next lets look at runtime performance.
```ruby
require 'action_pack'
require 'action_dispatch'
require 'benchmark/ips'
route_set = ActionDispatch::Routing::RouteSet.new
routes = ActionDispatch::Routing::Mapper.new route_set
routes.resources :foo
route = route_set.routes.first
match = ActionDispatch::Request.new("REQUEST_METHOD" => "GET")
no_match = ActionDispatch::Request.new("REQUEST_METHOD" => "POST")
Benchmark.ips do |x|
x.report("match") do
route.matches? match
end
x.report("no match") do
route.matches? no_match
end
end
__END__
Before:
$ be ruby -rallocation_tracer runtime.rb
Calculating -------------------------------------
match 17.145k i/100ms
no match 24.244k i/100ms
-------------------------------------------------
match 259.708k (± 4.3%) i/s - 1.303M
no match 453.376k (± 5.9%) i/s - 2.279M
After:
$ be ruby -rallocation_tracer runtime.rb
Calculating -------------------------------------
match 23.958k i/100ms
no match 29.402k i/100ms
-------------------------------------------------
match 465.063k (± 3.8%) i/s - 2.324M
no match 691.956k (± 4.5%) i/s - 3.469M
```
This tests tries to see how many times it can match a request per
second. Switching to method calls and string comparison makes the
successful match case about 79% faster, and the unsuccessful case about
52% faster.
That was fun!
|
|
|
|
|
| |
We don't need to add and delete from the conditions hash anymore, just
pass the regexp directly to the constructor.
|
|
|
|
|
| |
I want to change the real constructor to take a particular parameter for
matching the request method
|
|
|
|
|
| |
The string we create is almost always the same, so rather than joining
all the time, lets join once, then reuse that string everywhere.
|
|
|
|
|
|
| |
I would like to change the signature of the Route constructor. Since
the mapping object has all the data required to construct a Route
object, move the allocation to a factory method.
|
|
|
|
|
| |
we can directly turn it in to a regular expression here, so we don't
need to test its value twice
|
|
|
|
|
| |
The outer router object already keeps a hash of named routes, so we
should just use that.
|
|
|
|
|
| |
refactor the tests with a backwards compatible method call so we can rm
add_route2 from the journey router
|
|
|
|
|
| |
then we can let the mapping object derive stuff that the Route object
needs.
|
|
|
|
|
| |
now that we aren't doing options manipulations, we can just pass the
mapping object down and read values from it.
|