Commit Graph

12725 Commits

Author SHA1 Message Date
Xavier Noria
cbe7899f9d revises 877e42e
* A string in the example lacked quotes.

* The tests asserted stuff about :last_name, whereas
  test params do not have that key.

* But, the first one passed, why? After hitting my head against
  the wall and doing some obscure rituals realized the new
  #require had an important typo, wanted to iterate over the
  array argument (key), but it ran over its own hash keys
  (method #keys).

* Modified the test to prevent the same typo to happen again.

* The second test assigned to an unused variable safe_params
  that has been therefore removed.

* Grammar of the second test description.

* Since I was on it, reworded both test descriptions.
2015-08-28 17:15:20 +02:00
Gaurish Sharma
877e42e232 [Feature] params.require requires array of params
This PR adds ability to accept arrays which allows you to require multiple values in one method. so instead of this:

```ruby
params.require(:person).require(:first_name)
params.require(:person).require(:last_name)
```

Here it will be one line for each params, so say if I require 10params, it will be 10lines of repeated code which is not dry. So I have added new method which does this in one line:

```ruby
params.require(:person).require([:first_name, :last_name])
```

Comments welcome
2015-08-28 18:02:13 +05:30
Guillermo Iguaran
3cc7b0a239 Merge pull request #21396 from rodzyn/code-cleanup
Code cleanup
2015-08-28 00:45:44 -05:00
Aaron Patterson
bf203e471b Revert "this always sets :public to false, so just do that"
This reverts commit cae2b5bb59212961c4a35c939381ebece48d1177.

I am an idiot.
2015-08-27 14:16:01 -07:00
Aaron Patterson
cae2b5bb59 this always sets :public to false, so just do that 2015-08-27 13:47:37 -07:00
Aaron Patterson
d05d7e23d1 remove dependency on @cache_control ivar
eventually we'll remove this instance variable, but this is the first
step
2015-08-27 12:09:04 -07:00
Aaron Patterson
53265e8806 remove @etag ivar
we're storing the value in the headers hash, so lets just store the
value in one place.
2015-08-27 12:02:33 -07:00
Aaron Patterson
4e88f4f808 use the abstract API in modules
Modules should be using the API that the abstract modules use so that we
can move these modules between implementations
2015-08-27 12:00:56 -07:00
Aaron Patterson
f597dc5cf6 remove useless conditional
cookies are always stored as a string in the header hash, so it will not
need to be joined.
2015-08-27 11:38:52 -07:00
Aaron Patterson
14af136371 implement the API required by the abstract Rack request. 2015-08-27 11:13:11 -07:00
Aaron Patterson
97d088ebf2 use the non-hash dependent Rack utils API
eventually we will refactor this to not know about header hashes
2015-08-27 11:13:10 -07:00
Yves Senn
a62a164850 minor copy edit. [ci skip]
Follow up to #21384.
2015-08-27 14:20:09 +02:00
Yves Senn
6236cc46b9 Merge pull request #21384 from jeremyf/updating-ActionController-TestSession-to-behave-as-a-hash-with-indifferent
Updating TestSession to access with indifference
2015-08-27 14:16:30 +02:00
Marcin Olichwirowicz
fa216dc3b6 Code cleanup
Cleanup for `ActionDispatch::Http::Parameters` - no need for required libraries
and remove not used private method.

Apparently this method was used in `ActionDispatch::Http::Request` - fixed
by calling `Request::Utils` explicitly (as was done in other parts of the codebase)
2015-08-27 11:39:57 +02:00
Aaron Patterson
c967c5eb83 remove redefined method
Rack::Response::Helpers implements this method, so we can safely remove
it
2015-08-26 16:35:23 -07:00
Aaron Patterson
e6425f6eca Remove useless conditional
If the response method is defined, then calling `response` will return a
response.
2015-08-26 16:34:07 -07:00
Aaron Patterson
446b6855dc remove useless code
If AV::Rendering is mixed in, then `rendered_format` will be calculated
based on the current `lookup_context`, but calling `_process_format`
will set the `rendered_format` back on to the same lookup context where
we got the information in the first place!

Instead of getting information from an object, then setting the same
information back on to that object, lets just do nothing instead!
2015-08-26 16:17:29 -07:00
Aaron Patterson
3b8395a882 only call self.content_type= when there is a response
Apparently the AbstractController (whatever "abstract" means) is
expected to work without a request and response.
2015-08-26 15:31:23 -07:00
Aaron Patterson
2ceb16e539 Pull plain content type handling up to render
`render` is the only possible source for the `plain` option.  Pulling
the conditional up to the `render` method removes far away conditionals
2015-08-26 14:04:04 -07:00
Aaron Patterson
fa09bf44db stop passing the options hash to _process_format
We don't need to pass the full hash just to pull one value out.  It's
better to just pass the value that the method needs to know about so
that we can abstract it away from "options"
2015-08-26 13:51:28 -07:00
Aaron Patterson
d47438745e remove RackDelegation module
Since all controller instances are required to have a request and
response object, RackDelegation is no longer needed (we always have to
delegate to the response)
2015-08-26 11:53:15 -07:00
Aaron Patterson
6570ab7af8 remove useless method
the subclass sets the body on the response object, so we don't need the
superclass doing it too
2015-08-26 11:53:15 -07:00
Aaron Patterson
3cc35bed7a include ActionView::Rendering in the minimal controller
without this module, the content type is not set correctly
2015-08-26 11:53:15 -07:00
Kasper Timm Hansen
a20c5236bf Merge pull request #21387 from ronakjangir47/remove_dup_minitest
Removed duplicate require 'minitest/mock'
2015-08-26 20:27:30 +02:00
Aaron Patterson
54becd1a53 headers should delegate to the response object 2015-08-26 10:51:14 -07:00
Aaron Patterson
11ccdc8f17 remove useless status set
Now that `Controller#status=` just delegates to the response object,
we don't need to set the response on the controller and the response.
We can just set it in one place.
2015-08-26 10:51:14 -07:00
Aaron Patterson
ab0703eb59 remove useless conditional
we always have a response object, so there is no reason to test it
2015-08-26 10:51:13 -07:00
Aaron Patterson
a50d55a7ee remove ivars from the "protected" list
these ivars don't exist anymore, so we can remove them from the list
2015-08-26 10:51:13 -07:00
Aaron Patterson
27daea82d7 use the content_type method on the request object
since the controller always has a request on it, we can just ask the
request for the content type.
2015-08-26 10:51:13 -07:00
Aaron Patterson
02f5a28f40 ask the response for the status
The controller instance always has an instance of a response object.  We
should store the status code on the response object so that it's only
store in one place.
2015-08-26 10:51:13 -07:00
Aaron Patterson
109fb8e7a9 remove useless conditional
We always have a response object in controller instances, so we can
remove this conditional
2015-08-26 10:51:13 -07:00
Aaron Patterson
44454bdd8b remove useless conditional
controller instances always have a response object, so we don't need to
test to see if there is one, just always call to_a on the response.
2015-08-26 10:51:13 -07:00
Ronak Jangir
8d7bf97798 Removed duplicate requiring minitest/mock as it is already required in method_call_assertions 2015-08-26 19:43:54 +05:30
Jeremy Friesen
0258ef33a5 Updating TestSession to access with indifference
The following Rails code failed (with a `KeyError` exception) under
test:

```ruby
class ApplicationController < ActionController::Base
  def user_strategy
    # At this point:
    # ```ruby
    # session == {
    #   "user_strategy"=>"email",
    #   "user_identifying_value"=>"hello@world.com"
    # }
    # ```
    if session.key?(:user_strategy)
      session.fetch(:user_strategy)
    end
  end
end
```

When I checked the session's keys (`session.keys`), I got an array of
strings. If I accessed `session[:user_strategy]` I got the expected
`'email'` value. However if I used `session.fetch(:user_strategy)` I
got a `KeyError` exception.

This appears to be a Rails 4.2.4 regression (as the code works under
Rails 4.2.3).

Closes #21383
2015-08-26 09:08:18 -04:00
Aaron Patterson
51c7ac142d provide a request and response to all controllers
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:

  * 85a78d9358/actionpack/lib/action_controller/metal.rb (L221-L223)
2015-08-25 18:35:44 -07:00
Aaron Patterson
85a78d9358 :snip: whitespace 2015-08-25 17:23:10 -07:00
Aaron Patterson
27902c7e96 Fix another rack SPEC violation 2015-08-25 17:22:52 -07:00
Aaron Patterson
7401c4a1e9 rack SPEC doesn't allow first on the body
collect the body and make assert against the collected body
2015-08-25 17:02:07 -07:00
Aaron Patterson
d1b9a134cf move response allocation to the class level
we don't need an instance to figure out what type of response to
allocate.  Later we'll pull this up the stack and pass the response
object down
2015-08-25 16:34:06 -07:00
Aaron Patterson
67b2841fbe adding a direct dispatch method to controller classes
This saves a lambda and request allocation on each request.
2015-08-25 16:25:52 -07:00
Aaron Patterson
a26033b4a6 always dispatch to controllers the same way
controllers should always go through the `action` class method so that
their middleware is respected.
2015-08-25 16:00:20 -07:00
Aaron Patterson
702965c1b7 always return a controller class from the controller_class method
now the caller can just treat it like a regular controller even though
it will return a 404
2015-08-25 15:50:50 -07:00
Kasper Timm Hansen
7ee60d4c5b Merge pull request #21368 from rodzyn/remove_mocha
Get rid of mocha tests in actionpack - part 2
2015-08-25 21:46:30 +02:00
Rafael Mendonça França
2dd2d0c1e0 Merge pull request #21375 from rodzyn/unused_requires
Remove unused requires
2015-08-25 14:11:14 -03:00
Rafael Mendonça França
578618d8e6 Merge pull request #21366 from amitsuroliya/remove_unused_variable
Remove more unused block arguments
2015-08-25 14:08:17 -03:00
amitkumarsuroliya
8f0073bba1 Remove more unused block arguments 2015-08-25 22:23:23 +05:30
Marcin Olichwirowicz
38baf946c3 Remove unused requires
They are already required in `actionpack/lib/action_dispatch.rb` (L25-L26)
2015-08-25 18:13:45 +02:00
Marcin Olichwirowicz
a1772bba5d Make assert_index private
This `protected` keyword looks like some leftover, since
we are not using explicit receiver, this should go under `private`
2015-08-25 17:58:51 +02:00
Rafael Mendonça França
e84cc9afe4 Merge pull request #21345 from aditya-kapoor/trim-ap
Trim out least needed controllers from AP test suite
2015-08-25 12:44:34 -03:00
NehaGautam
c23e06c969 remove unused require ‘set’ 2015-08-25 18:54:53 +05:30
Marcin Olichwirowicz
00234f5619 Get rid of mocha tests - part 2 2015-08-25 09:28:06 +02:00
Rafael Mendonça França
f3e68ec16a Merge pull request #21094 from aditya-kapoor/add-missing-ap-tests
add missing test for action regexp for routing
2015-08-25 03:10:23 -03:00
Anshul Sharma
7b1c783630 Remove unused block arguments 2015-08-25 09:31:12 +05:30
amitkumarsuroliya
65c4076927 Remove unused block arguments 2015-08-25 07:49:47 +05:30
Aaron Patterson
c82248ea86 remove more direct env mutations 2015-08-24 17:07:48 -07:00
Aaron Patterson
d4e1f58fd8 remove another @env access 2015-08-24 16:39:47 -07:00
Aaron Patterson
cccc759ff7 remove more direct access to env 2015-08-24 16:14:42 -07:00
Aaron Patterson
a1ff5585bd fewer calls to env
We don't want to directly access the env hash
2015-08-24 15:59:30 -07:00
Aaron Patterson
c4c5918b68 stop using @env in the GET / POST methods
I want to implement this with something besides `@env` in the future, so
lets stop directly referencing it.
2015-08-24 14:57:05 -07:00
Aaron Patterson
ec9c237acc rm useless method
superclass already has this method, so remove this one
2015-08-24 14:21:27 -07:00
Aaron Patterson
7a62cc7d22 remove dead code 💣 2015-08-24 14:11:37 -07:00
Aaron Patterson
9b20b1cc0f pull up dispatcher allocation
the dispatcher class isn't configurable anymore, so pull up allocation
to the method that needs it.
2015-08-24 14:05:54 -07:00
Aaron Patterson
59e3b648c3 directly ask the request for the controller class
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
2015-08-24 14:01:11 -07:00
Aaron Patterson
74020eb255 use make_set helper method to generate route sets
We should keep the route set generation logic in one place
2015-08-24 13:59:40 -07:00
Aaron Patterson
b0e7db9ad9 remove useless ivar 2015-08-24 13:49:52 -07:00
Aaron Patterson
31cc4d621f remove setter for the dispatcher class
we don't need it anymore.  We always use the same dispatcher in tests.
2015-08-24 13:49:52 -07:00
Aaron Patterson
2237ee0596 subclass and delegate rather than mutating existing objects
If we subclass and augment the superclass, then we don't need to have
setters for particular things on the superclass.
2015-08-24 13:49:52 -07:00
Gaurav Sharma
a50872d51d temp files are no more require
`💅`
2015-08-25 01:36:05 +05:30
Aaron Patterson
337684fa28 use a custom request class to determine the controller class
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.
2015-08-24 12:06:41 -07:00
Carlos Antonio da Silva
35decf4b6b Merge pull request #21339 from deepj/unused-block-arguments
Remove unused block arguments
2015-08-24 13:40:03 -03:00
Rafael Mendonça França
9e5ba3c86b Merge pull request #21355 from akihiro17/remove-variables
Remove unused variables
2015-08-24 13:36:10 -03:00
Kasper Timm Hansen
b9825801e2 Merge pull request #21321 from rodzyn/removing_mocha
Get rid of mocha tests in actionpack - part 1
2015-08-24 12:44:01 +02:00
Marcin Olichwirowicz
3a161e65e7 Get rid of mocha tests - part 1 2015-08-24 12:24:07 +02:00
akihiro17
7adef79e14 Remove unused variables 2015-08-24 17:33:19 +09:00
Aaron Patterson
9503e65b97 use methods on the request object instead of accessing env 2015-08-23 17:25:13 -07:00
Aaron Patterson
71d0b61f3a use Request#path_info instead of direct ENV access
we already have a request, so we should use the methods on the request
to access the path info information
2015-08-23 17:22:21 -07:00
Aaron Patterson
feb248ca76 remove env access from debug_exceptions
Creates fewer request objects and helps to abstract away from internals
2015-08-23 17:18:02 -07:00
Aaron Patterson
f16a33b68e remove more env access 2015-08-23 17:09:13 -07:00
Aaron Patterson
97c65aa144 remove more env access 2015-08-23 16:53:41 -07:00
Aaron Patterson
7de86d2cf3 remove more env access 2015-08-23 16:48:37 -07:00
Aaron Patterson
a682b44e70 convert more @env access to get / set header 2015-08-23 16:36:43 -07:00
Aaron Patterson
f038ed2d2a remove usage of @env
try to remove dependencies on `@env` so we can have more flexible
internals
2015-08-23 16:16:28 -07:00
Aditya Kapoor
b393c6af92 Trim out unneeded controllers from AP test suite 2015-08-24 01:02:14 +05:30
deepj
dbfab58457 Remove unused block arguments 2015-08-23 16:06:29 +02:00
Ronak Jangir
688bcc8e5b Another place to use a request object in NullSessionHash
May be missed in 5fe141638f1243ac6ae187ae14aa398b4c1875a2 commit
Also fixes the broken build
2015-08-23 19:11:37 +05:30
Aaron Patterson
5fe141638f use a request object in the session middleware
This commit allows us to use one request object rather than allocating
multiple request objects to deal with the session.
2015-08-22 17:57:45 -07:00
Aaron Patterson
4f244f7cab move more @env access to method calls
We're going to implement storing env values differently in the future,
so let's disconnect these methods from the instance variables
2015-08-22 16:01:53 -07:00
Aaron Patterson
3ca8f91543 move ORIGINAL_SCRIPT_NAME to the metaprogrammed methods 2015-08-22 15:56:08 -07:00
Aaron Patterson
39837b1709 metaprogram the HTTP_X_REQUEST_ID method
we're already doing this with a bunch of other header data.
2015-08-22 15:52:50 -07:00
Aaron Patterson
64f6dc6daf use body_stream instead of getting the env value ourselves
we have a method that knows how to get rack.input, so lets use that.
2015-08-22 15:52:15 -07:00
Aaron Patterson
3e0b9326f9 convert @env use to get / set header
We need to abstract the internals of the request object away from this
instance variable so that the values for `@env` can be calculated in a
different way.
2015-08-22 15:50:15 -07:00
Aaron Patterson
383f18b9ec use get / set header to avoid depending on the env ivar 2015-08-22 15:40:43 -07:00
eileencodes
f15a2609cb Fix Railties test failure for asset routes
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`.
2015-08-22 12:30:58 -04:00
eileencodes
4276b214f8 Refactor to remove controller class from route to request
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]
2015-08-22 09:44:24 -04:00
Aaron Patterson
ec760e67fd set cached values in the env hash 2015-08-21 17:22:44 -07:00
Aaron Patterson
7bd34c107a stop directly accessing @env in mime_negotiation
we want to go through methods to access `env` because in the future that
ivar may not be available, or may be calculated lazily
2015-08-21 17:15:21 -07:00
Aaron Patterson
992bf079e8 use public API to fetch the parameter filter
now the parameter filter doesn't need to know about the env hash in
these two methds.
2015-08-21 17:08:24 -07:00
Aaron Patterson
bce4ff70dd use methods on the request object to implement fetch
Now the Headers internals don't depend on the env hash.
2015-08-21 16:59:13 -07:00
Aaron Patterson
c0c726849b dup the env hash on Header#env
This prevents external mutations from impacting the internals of the
request or the Header object.
2015-08-21 16:59:13 -07:00
Aaron Patterson
fbf6b98c95 use accessors on the request object for manipulating env
this reduces the API footprint for the env hash so that we can be more
flexible when changing API in the future
2015-08-21 16:59:12 -07:00
Aaron Patterson
ba2173a10d use set_header rather than []=
This allows us to avoid calling `env_name` twice.
2015-08-21 16:59:12 -07:00
Aaron Patterson
1fbf5ad7f7 dup the request and mutate its headers object.
duping the request will dup it's underlying env hash.
2015-08-21 16:59:12 -07:00
eileencodes
ec9c6d5846 Remove unnecessary caching
`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.
2015-08-21 14:36:51 -04:00
Aaron Patterson
34fa6658dd pass a request object to the headers object 2015-08-21 11:21:10 -07:00
Aaron Patterson
c6cfcc6124 move header allocation to a helper method
I'm going to change the constructor, so it's easier to do it in one
place.
2015-08-21 11:21:10 -07:00
Andrew White
95cb2e3a8a Merge pull request #21106 from amitsuroliya/fix_routing_test
Remove duplicity in tests
2015-08-21 11:25:38 +01:00
Aaron Patterson
867810cdfa set route precedence at allocation time
This way we can make the Route object a read-only data structure.
2015-08-20 15:34:18 -07:00
Aaron Patterson
51211a94bd point at rack master 2015-08-20 13:45:11 -07:00
Marcin Olichwirowicz
a8d0084c69 Remove dead code 2015-08-19 19:14:38 +02:00
Aaron Patterson
7187339854 make the routes reader private
nobody should be touching the routes hash without going through the
NamedRouteCollection object.
2015-08-18 16:33:18 -07:00
Aaron Patterson
62383ddecc don't touch internals
We shouldn't be messing with the NamedRouteCollection internals.  Just
ask the object if the named route is in there.
2015-08-18 16:30:01 -07:00
Aaron Patterson
d993cb3629 drop array allocations when building paths
```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}
```
2015-08-18 15:57:11 -07:00
Aaron Patterson
4d9475bef9 symbols will always be constructed with strings. 💣 2015-08-18 15:20:19 -07:00
Aaron Patterson
01d88953e2 drop string allocations for each resource
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}
```
2015-08-18 15:12:44 -07:00
Rafael Mendonça França
88a1800526 Remove unreached default value
verb_matcher never returns nil.
2015-08-17 23:22:59 -03:00
Aaron Patterson
0b476de445 use the strategy pattern to match request verbs
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!
2015-08-17 18:17:55 -07:00
Aaron Patterson
c989e2c56f switch Route constructors and pass in the regexp
We don't need to add and delete from the conditions hash anymore, just
pass the regexp directly to the constructor.
2015-08-17 16:43:40 -07:00
Aaron Patterson
bb10030802 split the verb regex from the constraints hash
verb matching is very common (all routes besides rack app endpoints
require one).  We will extract verb matching for now, and use a more
efficient method of matching (then regexp) later
2015-08-17 16:39:26 -07:00
Aaron Patterson
23cfdd4b71 test the verb method on the route, specifically 2015-08-17 16:36:31 -07:00
Aaron Patterson
c42db41f54 routes are always constructed with a hash for the conditions 2015-08-17 16:30:53 -07:00
Aaron Patterson
1ce74b009f introduce an alternate constructor for Route objects
I want to change the real constructor to take a particular parameter for
matching the request method
2015-08-17 16:08:39 -07:00
Aaron Patterson
559e7f9450 drop object allocation during routes setup
This commit introduces a functional Path AST visitor and implements
`each` on the AST in terms of the functional visitor.  The functional
visitor doesn't maintain state, so we only need to allocate one of them.

Given this benchmark route file:

```ruby
require 'action_pack'
require 'action_dispatch'

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{|i|
    routes.resource :omglol
  }
end

result.find_all { |k,v| k.first =~ /git\/rails/ }.sort_by { |k,v|
  v.first
}.each { |k,v|
  p k => v
}
```

node.rb line 17 was in our top 3 allocation spot:

```
{["/Users/aaron/git/rails/actionpack/lib/action_dispatch/journey/nodes/node.rb", 17, :T_OBJECT]=>[31526, 0, 28329, 0, 2, 1123160]}
{["/Users/aaron/git/rails/actionpack/lib/action_dispatch/routing/mapper.rb", 2080, :T_IMEMO]=>[34002, 0, 30563, 0, 2, 1211480]}
{["/Users/aaron/git/rails/actionpack/lib/action_dispatch/routing/mapper.rb", 2071, :T_IMEMO]=>[121934, 1, 109608, 0, 7, 4344400]}
```

This commit eliminates allocations at that place.
2015-08-17 15:57:06 -07:00
Aaron Patterson
8d7b883f33 avoid is_a? checks
add another predicate method so we can avoid is_a checks
2015-08-17 15:28:23 -07:00
Aaron Patterson
56f734a361 pull RegexpOffsets in to a method
we don't really need this visitor
2015-08-17 15:11:20 -07:00
Aaron Patterson
15bc6b630f required_defaults is always passed in, remove conditional
Routes are always constructed with a list of required_defaults, so
there's no need to check whether or not it's nil
2015-08-17 15:11:20 -07:00
Marcin Olichwirowicz
48a240bcbe Fix master build 2015-08-17 23:30:32 +02:00
Aaron Patterson
d12ff4fa50 use predicate methods to avoid is_a? checks
we may want to change the name of the class at some point, so it's
better to use a predicate
2015-08-17 13:51:39 -07:00
Aaron Patterson
e9777ef62e default pattern to use a joined string
The string we create is almost always the same, so rather than joining
all the time, lets join once, then reuse that string everywhere.
2015-08-17 13:51:38 -07:00
Rafael Mendonça França
15fd2586a8 Merge pull request #21252 from rodzyn/improve_params_parser
Improve params parser
2015-08-17 13:20:09 -03:00
Jon Atack
51b237c955 [skip ci] Fix minor typo 2015-08-17 16:02:56 +02:00
Marcin Olichwirowicz
9366d622be Cleanup ActionDispatch:ParamsParser 2015-08-17 11:38:37 +02:00
Aaron Patterson
fe19d07138 move route allocation to a factory method on the mapping object
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.
2015-08-15 14:34:37 -07:00
Aaron Patterson
703275ba70 use the mapper to build the routing table
We should build the routes using the user facing API which is `Mapper`.
This frees up the library internals to change as we see fit. IOW we
shouldn't be testing internals.
2015-08-15 14:32:04 -07:00
Aaron Patterson
05eea6a2c3 only process via once
we can directly turn it in to a regular expression here, so we don't
need to test its value twice
2015-08-15 14:32:03 -07:00
eileencodes
f6232a518b Refactor how assign_parameters sets generated_path & query_string_keys
This is part of a larger refactoring on controller tests. We needed to
move these methods here so that we could get rid of the `|| key ==
:action || key == :controller` in `assign_parameters`. We know this is
ugly and intend to fix it but for now `generate_extras` needs to be used
in the two methods to access the path and the query_string_keys.

We're adding `:controller` and `:action` to the `query_string_keys`
because we always need a controller and action. If someone passed
`action` or `controller` in in there test they are unambigious - we
know they have to go into the query params.
2015-08-15 13:23:41 -04:00
Marcin Olichwirowicz
174b9a3097 Initialize symbols instead of mapping to_sym on the set of strings 2015-08-15 17:45:13 +02:00
Aaron Patterson
a293812bff only keep one hash of named routes
The outer router object already keeps a hash of named routes, so we
should just use that.
2015-08-14 18:06:48 -07:00
Aaron Patterson
4bdd92d9fd rm add_route2
refactor the tests with a backwards compatible method call so we can rm
add_route2 from the journey router
2015-08-14 16:25:03 -07:00
Aaron Patterson
6c48d9392f pass pass the mapping object down the add_route stack
then we can let the mapping object derive stuff that the Route object
needs.
2015-08-14 16:13:26 -07:00
Aaron Patterson
5ba6966766 pass the mapping object to build_route
now that we aren't doing options manipulations, we can just pass the
mapping object down and read values from it.
2015-08-14 14:41:48 -07:00
Aaron Patterson
68dd5abf14 remove process_path
since we've extracted the `to` initialization, there's no need for
`process_path`
2015-08-14 14:05:00 -07:00
Aaron Patterson
565582c0f5 explicitly return nil from get_to_from_path
if `to` was initialized, this method would return, so we can eliminate
the to ||= in the conditional.  Finally, let's return a nil in the else
block so that it's explicit that this method can return nil
2015-08-14 12:08:30 -07:00
Aaron Patterson
b543ee74f4 extract method on determining :to from the path
Eventually we'll pull this up and delete `process_path`.
2015-08-14 12:03:08 -07:00
Aaron Patterson
b10b279b97 deprecate passing a string for both the beginning path and :path option 2015-08-14 11:55:50 -07:00
Aaron Patterson
b6146b0d96 rm path_params method
We don't need a method for something like this.  I want to pull this up
the stack as well and move the module + :controller ArgumentError up the
stack as well
2015-08-14 11:03:49 -07:00
Aaron Patterson
4a591ce2f8 extract method on wildcard path parameter handling 2015-08-14 10:54:04 -07:00
Aaron Patterson
b592c5b607 pass the path ast down
now we don't need to add it to a hash and delete it from the hash later
just to pass it around
2015-08-14 10:44:49 -07:00
Aaron Patterson
aaaa67902e pull up path parsing
`add_route` needs the AST, so rather than shove it in a hash and delete
later, lets move parsing up the stack so we can pass down later
2015-08-14 10:39:33 -07:00
Aaron Patterson
7fa6600b52 use predicate methods instead of hard coding verb strings
also change the feeler to subclass AD::Request so that it has all the
methods that Request has
2015-08-14 10:39:33 -07:00
Aaron Patterson
ad311f215d remove hard coded regular expression 2015-08-14 10:39:33 -07:00