aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/journey
Commit message (Collapse)AuthorAgeFilesLines
* Merge pull request #29191 from ↵Kasper Timm Hansen2017-05-291-5/+5
|\ | | | | | | | | bogdanvlviv/pass_params_filename_lineno_to_class_eval Pass params __FILE__ and __LINE__ + 1 if class_eval with <<
| * Pass params __FILE__ and __LINE__ + 1 if class_eval with <<bogdanvlviv2017-05-291-5/+5
| |
* | Merge pull request #29176 from bogdanvlviv/define-path-with__dir__Matthew Draper2017-05-261-1/+1
|\ \ | |/ |/| Define path with __dir__
| * Define path with __dir__bogdanvlviv2017-05-231-1/+1
| | | | | | | | | | | | ".. with __dir__ we can restore order in the Universe." - by @fxn Related to 5b8738c2df003a96f0e490c43559747618d10f5f
* | Remove unused simulate methodeileencodes2017-05-221-8/+0
|/ | | | | | This method was only used in the Rails tests and not by other methods in the Rails simulator. Because it's a no-doc'd class it should be safe to remove without deprecation.
* Maintain original encoding from patheileencodes2017-05-121-0/+2
| | | | | | | | | When the path info is read from the socket it's encoded as ASCII 8BIT. The unescape method changes the encoding to UTF8 but it should maintain the encoding of the string that's passed in. This causes parameters to be force encoded to UTF8 when we don't actually know what the encoding of the parameter should be.
* Remove `:doc:` in `:nodoc:` class [ci skip]Ryuta Kamizono2017-05-011-2/+2
| | | | | The `:doc:` was added in bc478158 but originally `UriEncoder` is a `:nodoc:` class.
* Add periodJon Moss2017-04-301-1/+1
| | | | [ci skip]
* Add docs for Router::Utils.unescape_uri methoddixpac2017-04-301-0/+4
|
* [docs] fix ActionDispatch documentationHrvoje Šimić2017-03-135-5/+11
|
* Correct spellingBenjamin Fleischer2017-02-051-1/+1
| | | | | | | ``` go get -u github.com/client9/misspell/cmd/misspell misspell -w -error -source=text . ```
* Merge pull request #27647 from Shopify/fully-eagerload-journeyRafael França2017-01-303-0/+22
|\ | | | | Fully initialize routes before the first request is handled
| * Fully initialize routes before the first request is handledJean Boussier2017-01-183-0/+22
| | | | | | | | | | | | | | | | | | | | | | | | `AD::Journey::GTG::Simulator` is lazily built the first time `Journey::Router#find_routes` is invoked, which happens when the first request is served. On large applications with many routes, building the simulator can take several hundred milliseconds (~700ms for us). Triggering this initialization during the boot process reduces the impact of deploys on the application response time.
* | class Foo < Struct.new(:x) creates an extra unneeded anonymous classAkira Matsuda2017-01-131-1/+1
|/ | | | because Struct.new returns a Class, we just can give it a name and use it directly without inheriting from it
* Use `next` instead of `break`; avoid terminating whole loopJon Moss2016-12-291-1/+1
| | | | | | | | | | | | | | We want to avoid terminating the whole loop here, because it will cause parameters that should be removed to not be removed, since we are terminating early. In this specific case, `param2` is processed before `param1` due to the reversing of `route.parts`, and since `param2` fails the check on this line, it would previously cause the whole loop to fail, and `param1` would still be in `parameterized_parts`. Now, we are simply calling `next`, which is the intended behavior. Introduced by 8ca8a2d773b942c4ea76baabe2df502a339d05b1. Fixes #27454.
* Optimize Journey::Route#scoreBen Hughes2016-12-282-5/+14
| | | | | | | | Scoring routes based on constraints repeated many type conversions that could be performed in the outer loop. Determinations of score and fitness also used Array operations that required allocations. Against my benchmark with a large routeset, this reduced object allocations by over 30x and wall time by over 3x.
* Shave a couple of allocations off Journey scan & parseMatthew Draper2016-12-253-203/+207
|
* Privatize unneededly protected methods in Action PackAkira Matsuda2016-12-241-3/+3
|
* Add more rubocop rules about whitespacesRafael Mendonça França2016-10-298-12/+12
|
* Fix :stopdoc: to :startdoc: [ci skip]Ryuta Kamizono2016-10-281-1/+1
|
* Remove all Journey constant from public APIRafael Mendonça França2016-10-265-7/+17
| | | | | | There were never public API only there by mistake. [ci skip]
* Show an "unmatched constraints" error for mismatching and present paramsChris Carter2016-10-031-1/+5
| | | | | | | | | | | | Currently a misleading "missing required keys" error is thrown when a param fails to match the constraints of a particular route. This commit ensures that these params are recognised as unmatching rather than missing. Note: this means that a different error message will be provided between optimized and non-optimized path helpers, due to the fact that the former does not check constraints when matching routes. Fixes #26470.
* Fix broken comments indentation caused by rubocop auto-correct [ci skip]Ryuta Kamizono2016-09-141-11/+11
| | | | | | All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772. But comments was still kept absolute position. This commit aligns comments with method definitions for consistency.
* Fix broken heredoc indentation caused by rubocop auto-correctRyuta Kamizono2016-09-031-1/+1
| | | | | | All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772. But heredocs was still kept absolute position. This commit aligns heredocs indentation for consistency.
* Merge pull request #26156 from sfaxon/route_visualizer_fixRafael França2016-08-161-1/+3
|\ | | | | fix Rails.application.routes.router.visualizer for router debugging
| * fix Rails.application.routes.router.visualizer for router debuggingSeth Faxon2016-08-131-1/+3
| | | | | | | | fixes error due to Routes#partitioned_routes being removed
* | Add three new rubocop rulesRafael Mendonça França2016-08-163-4/+4
|/ | | | | | | | Style/SpaceBeforeBlockBraces Style/SpaceInsideBlockBraces Style/SpaceInsideHashLiteralBraces Fix all violations in the repository.
* revises more Lint/EndAlignment offensesXavier Noria2016-08-081-2/+2
|
* Add `Style/EmptyLines` in `.rubocop.yml` and remove extra empty linesRyuta Kamizono2016-08-071-1/+0
|
* applies remaining conventions across the projectXavier Noria2016-08-065-6/+4
|
* normalizes indentation and whitespace across the projectXavier Noria2016-08-064-173/+173
|
* remove redundant curlies from hash argumentsXavier Noria2016-08-061-1/+1
|
* modernizes hash syntax in actionpackXavier Noria2016-08-061-1/+1
|
* applies new string literal convention in actionpack/libXavier Noria2016-08-0616-53/+53
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* Merge pull request #23103 from rails/refactor-handling-of-action-defaultJeremy Daer2016-04-241-2/+7
|\ | | | | | | Refactor handling of :action default in routing
| * Refactor handling of :action default in routingAndrew White2016-02-161-2/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The longstanding convention in Rails is that if the :action parameter is missing or nil then it defaults to 'index'. Up until Rails 5.0.0.beta1 this was handled slightly differently than other routing defaults by deleting it from the route options and adding it to the recall parameters. With the recent focus of removing unnecessary duplications this has exposed a problem in this strategy - we are now mutating the request's path parameters and causing problems for later url generation. This will typically affect url_for rather a named url helper since the latter explicitly pass :controller, :action, etc. The fix is to add a default for :action in the route class if the path contains an :action segment and no default is passed. This change also revealed an issue with the parameterized part expiry in that it doesn't follow a right to left order - as soon as a dynamic segment is required then all other segments become required. Fixes #23019.
* | [ci skip] Replace usage of rake routes with rails routesAbhishek Jain2016-02-251-1/+1
| |
* | Add `internal` attribute to routesJon Moss2016-02-221-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This is meant to provide a way for Action Cable, Sprockets, and possibly other Rack applications to mark themselves as internal, and to exclude themselves from the routing inspector, and thus `rails routes` / `rake routes`. I think this is the only way to have mounted Rack apps be marked as internal, within AD/Journey. Another option would be to create an array of regexes for internal apps, and then to iterate over that everytime a request comes through. Also, I only had the first `add_route` method set `internal`'s default to false, to avoid littering it all over the codebase.
* | Remove unused Journey codeJon Moss2016-02-172-8/+0
|/ | | | | | | | | | - `VERSION` shouldn't be there anymore since Journey is technically part of Action Dispatch now (and thus Action Pack, and follows the normal Rails versioning scheme) - `backwards.rb` was only in the file tree because early in the history or Journey (back in 2011!), it was moved from under the Rack namespace, to its own namespace, Journey! This file is no longer required, and is assigning constants that are no longer needed.
* Replace x.times.map{} with Array.new(x){}Viktar Basharymau2016-01-021-1/+1
| | | | | | | | | | | | | | | | | | | | | | | The former is slightly more readable, performant and has fewer method calls. ```ruby Benchmark.ips do |x| x.report('times.map') { 5.times.map{} } x.report('Array.new') { Array.new(5){} } x.compare! end __END__ Calculating ------------------------------------- times.map 21.188k i/100ms Array.new 30.449k i/100ms ------------------------------------------------- times.map 311.613k (± 3.5%) i/s - 1.568M Array.new 590.374k (± 1.2%) i/s - 2.954M Comparison: Array.new: 590373.6 i/s times.map: 311612.8 i/s - 1.89x slower ```
* Merge pull request #21849 from yui-knk/refactor_regexp_to_stringAndrew White2015-10-121-1/+1
|\ | | | | Change `Journey::Route#verb` to return string instead of regexp.
| * Change `Journey::Route#verb` to return string instead of regexp.yui-knk2015-10-031-1/+1
| | | | | | | | | | | | | | | | | | 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.
* | used predicate methods to avoid is_a? checksRonak Jangir2015-10-102-3/+5
|/
* File encoding is defaulted to utf-8 in Ruby >= 2.1Akira Matsuda2015-09-182-4/+0
|
* Fix route creation when format is a blank stringeileencodes2015-09-021-1/+1
| | | | | | | | | | | | | | | | | Commit bff61ba, while reducing allocations, caused a regression when an empty format is passed to a route. This can happen in cases where you're using an anchor tag, for example: `https://example.com/parent/575256966.#child_1032289285`. Because of this change `format` was getting sent in `parameterized_parts` when previously it was not included. This resulted in blank `format`'s being returned as `.` when if there was an extension included it would be `.extension`. Since there was no extension this caused incorrect URL's. The test shows this would result in `/posts/show/1.` instead of `/posts/show/1` which causes bad urls since the format is not present.
* set route precedence at allocation timeAaron Patterson2015-08-201-6/+4
| | | | This way we can make the Route object a read-only data structure.
* drop array allocations when building pathsAaron Patterson2015-08-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ```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} ```
* drop string allocations for each resourceAaron Patterson2015-08-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Eagerly calculate and cache the name of Symbol objects in the path AST. This drops about 26 string allocations per resource: ```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=>116084} {:T_HASH=>122015} {:T_STRING=>172647} {:T_IMEMO=>371132} {:T_ARRAY=>433056} After: {: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} ```
* Remove unreached default valueRafael Mendonça França2015-08-171-1/+1
| | | | verb_matcher never returns nil.
* use the strategy pattern to match request verbsAaron Patterson2015-08-171-6/+48
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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!