Commit Graph

12725 Commits

Author SHA1 Message Date
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
Aaron Patterson
c3284e2a36 implement requirements in terms of routes 2015-08-14 10:39:33 -07:00
Aaron Patterson
60adf118a6 implement the asts method in terms of paths / patterns
Eventually I want to eliminate the FakeSet test class
2015-08-14 10:39:32 -07:00
Aaron Patterson
61437232a9 extract ast finding to a method
I'm going to reimplement this using route objects, so it will be easier
if we just change ast access to go through a method rather than hashes
2015-08-14 10:39:32 -07:00
Aaron Patterson
715abbbb33 stop adding path_info to the conditions hash
we don't need to keep adding it and deleting if from hashes.
2015-08-14 10:39:32 -07:00
Aaron Patterson
1eb6b4a679 pull up path normalization.
Eventually I want to pull up AST generation so that we don't have to add
it to the `conditions` hash.
2015-08-14 10:39:32 -07:00
Aaron Patterson
95a5d177cc build_path doesn't need the path variable anymore
It just constructs a Path::Pattern object with the AST that it already
has
2015-08-13 15:44:15 -07:00
Aaron Patterson
947ebe9a6d remove Strexp
This was a useless object.  We can just directly construct a
Path::Pattern object without a Strexp object.
2015-08-13 15:42:46 -07:00
Aaron Patterson
4868692687 pass anchor directly to Pattern
the caller already has it, there is no reason to pack it in to an object
and just throw that object away.
2015-08-13 15:16:25 -07:00
Aaron Patterson
36f26fd47e we already have access to the AST, so just use it 2015-08-13 15:03:20 -07:00
Aaron Patterson
b3d73e789c remove default arguments that aren't used
we always pass all parameters, so there is no reason to provide default
arguments.
2015-08-13 14:19:58 -07:00
Aaron Patterson
45d594fa53 pull up options_constrants extraction 2015-08-13 14:15:04 -07:00
Aaron Patterson
b778f6348b remove as
the caller already has access to `as`, so we can stop passing it around.
2015-08-13 14:04:02 -07:00
Aaron Patterson
e38a456faf remove anchor from mapping
the same value that is extracted from the options hash earlier is
returned, so we don't need to pass it in in the first place.  The caller
already has the data, so stop passing it around.
2015-08-13 13:58:16 -07:00
Aaron Patterson
aef421ed9d pull anchor extraction up
this way we don't have to mutate the options hash so far away from where
the user passed it in
2015-08-13 13:55:03 -07:00
Aaron Patterson
33dc653466 raise if anchor is passed to scope
The `anchor` parameter [is overridden](b4b4a611d0/actionpack/lib/action_dispatch/routing/mapper.rb (L1528)) unless it
is directly passed to `match`, so setting it in a scope must be a
mistake.
2015-08-13 13:41:03 -07:00
Aaron Patterson
ba7602b881 remove the add_request_method method
I didn't like this method because it mutates the parameters.  Now that
the method is so small, just push it up to `initialize`
2015-08-12 17:24:23 -07:00
Aaron Patterson
a4f7809472 remove side effects in normalize_defaults
now the `@defaults` variable doesn't need to be set before calling
`normalize_defaults`
2015-08-12 17:10:44 -07:00
Aaron Patterson
3e3e23f048 remove unnecessary deletes
These three options are stored in the `scope` chain outside of the
options hash.  If they are in the options hash, then someone passed them
in to `match` and they don't really do anything.  So lets remove the
code.
2015-08-12 17:04:32 -07:00
Aaron Patterson
3955688440 pull format out of the options hash
remove `format` from the options hash in the scope chain so that we
don't need to remove it later
2015-08-12 16:54:35 -07:00
Aaron Patterson
ec895189e4 pull formatted up the stack
this reduces the number of times we have to mutate the options hash.
2015-08-12 16:54:35 -07:00
Aaron Patterson
d61e3c79dc add a regression test for scoped format params
This just ensures that `format` is applied to things inside the scope
2015-08-12 16:54:35 -07:00
Rafael Mendonça França
7d4ad74ce5 Merge pull request #21214 from rodzyn/fewer_objects_and_refactoring
Fewer objects and refactoring
2015-08-12 20:15:37 -03:00
Marcin Olichwirowicz
fc22cb88ed Simplify code
Since we are always responding with an array and using `any?`, we don't
need to check if an array is empty
2015-08-13 01:00:49 +02:00
Marcin Olichwirowicz
0c15b85d5d Avoid unnecessary MatchData objects 2015-08-13 00:56:29 +02:00
Aaron Patterson
2a05a72e6a store via outside the options hash
Now we don't have to manually remove this from the options hash since
the scope stores it outside of "options"
2015-08-12 15:54:24 -07:00
Aaron Patterson
f514c9c04a don't mutate the caller's variables
Remove the `options` reader from `Resource` because nobody needs to see
that hash.  Also remove mutations on the options hash in
`apply_common_behavior_for` because leaving the side effects in that
method makes it difficult to understand what is going on in the caller.
2015-08-12 15:50:14 -07:00
Aaron Patterson
33d20ea184 store :only and :except outside the normal options hash
these two keys have a different merge strategy, and they also just get
removed from the options hash later in the code.  If we store them in a
separate place, then we don't need to remove them later
2015-08-12 15:30:43 -07:00
Aaron Patterson
e2735b2b32 add a regression test for adding arbitrary keys to scope 2015-08-12 15:17:21 -07:00
Aaron Patterson
1c94317539 add a method to Scope for getting mapping options
Eventually we don't want to expose the "options" hash from scope, only
read values from it.  Lets start by adding a reader method.
2015-08-12 14:30:54 -07:00
Aaron Patterson
58117fadae pull via checking up to via extraction
now we don't need to construct a Mapping object just to get an
ArgumentError if there is no `via` parameter provided.
2015-08-12 14:30:53 -07:00
Aaron Patterson
b46c67fb47 pull via all the way out of add_route 2015-08-12 14:30:53 -07:00
Aaron Patterson
b106dddfaf fix via handling when it's in a scope 2015-08-12 14:30:53 -07:00
Aaron Patterson
4c641c6e36 add a test for adding "via" using scope 2015-08-12 14:30:53 -07:00
Aaron Patterson
b59ff24207 pull via extraction up
We're going to try pulling this up further, and check `via` validity
sooner.  This way we don't have to do a bunch of processing on `options`
hashes only to find out that the route is incorrect
2015-08-12 14:30:53 -07:00
Aaron Patterson
f88c68a819 simplify split_constraints
If we do the Regexp verification in a second method, then the
`split_constraints` method gets much easier.
2015-08-12 14:30:53 -07:00
Aaron Patterson
c10d7d1690 remove side effects from normalize_format 2015-08-12 14:30:53 -07:00
Aaron Patterson
b9a622f817 switch === to case / when 2015-08-12 14:30:52 -07:00
Aaron Patterson
463339c4bb make split_constraints more functional.
I don't want `split_constraints` to mutate any instance variables.  That
way it's easier to move the method around and understand what it does
(it has no side effects)
2015-08-12 14:30:52 -07:00
Aaron Patterson
3042b71a7a make constraints more functional
I don't want to rely on mutating ivars.  This gives me more freedom when
refactoring
2015-08-12 14:30:52 -07:00
Aaron Patterson
cbf1617015 only call split_constraints once 2015-08-11 18:23:25 -07:00
Aaron Patterson
3420849f85 only do is_a? checks on options_constraints once
we don't need to do it so many times.
2015-08-11 18:17:05 -07:00
Aaron Patterson
ea4da199b7 Mapping instances don't need scope anymore 2015-08-11 18:10:41 -07:00
Aaron Patterson
175280ccb5 pull scope[:constraints] up
Now we only need to call `split_constraints` possibly twice!
2015-08-11 18:06:54 -07:00
Aaron Patterson
0988ad0fa7 pull :format up a little bit
apparently `format` can also come from the scope options, so we need to
extract it there too.
2015-08-11 18:06:53 -07:00
Sean Griffin
e69364bc2d Merge pull request #21203 from denniss/issue-21199
Authorization scheme should be case insensitive. Fixes #21199
2015-08-11 17:25:00 -06:00
Aaron Patterson
97d7dc48d6 pull to up
this way we don't have to insert / delete it from the options hash so
many times.
2015-08-11 16:16:09 -07:00
Aaron Patterson
c25d1707b9 push scope access up for modules
eventually we'll remove the need to access `scope` inside the Mapping
object.
2015-08-11 16:16:09 -07:00
Dennis Suratna
dec2f52fa4 Authorization scheme should be case insensitive. Fixes #21199 2015-08-11 15:59:44 -07:00
Aaron Patterson
41e7923cd4 path is never nil 2015-08-11 14:50:15 -07:00
Aaron Patterson
763dd50a76 split options hash and pass values down
`using_match_shorthand?` doesn't need to know that an options hash
exists.  Also use this opportunity to make the boolean logic a little
more sane
2015-08-11 14:49:19 -07:00
Aaron Patterson
0c3f8e3f02 pull option duping up 2015-08-11 14:49:19 -07:00
Aaron Patterson
1a830cbd83 split paths by type
this simplifies the "downstream" logic since we know we'll only be
dealing with one particular type
2015-08-11 14:49:19 -07:00
Aaron Patterson
7df7c707ab one fewer hash mutation 2015-08-11 14:49:19 -07:00
Aaron Patterson
5935e4c882 push option decomposition up a bit more
I think we can find the original place where `action` is added to the
options hash now.
2015-08-11 14:49:19 -07:00
Aaron Patterson
934bdf6724 push action option extraction up one frame. 2015-08-11 14:49:18 -07:00
Aaron Patterson
97bbde7600 pull up the "options.delete(:controller)" logic
we want to try to pull this logic up to where the user actually passed
in "controller" so that it's close to the related call.  That way when
we're down the stack, we don't need to wonder "why are we doing this?"
2015-08-11 14:49:18 -07:00
Robin Dupret
f51d142881 Tiny documentation fixes [ci skip] 2015-08-11 15:35:35 +02:00
Rafael Mendonça França
30608648ef Only use path if the key is not present
There are some cases where :path is nil on option and we should respect
that.
2015-08-10 22:51:46 -03:00
Aaron Patterson
8adf25a632 try to pass fewer options to scope
We already know how to handle `path`, so lets just handle it on our own.
2015-08-10 17:57:17 -07:00
Aaron Patterson
7f3cfb6067 always cast name to a symbol, and never to_s it
All callers of `action_path` interpolate the return value in to a
string, so there is no need for the method to to_s it.  to_sym on a
symbol will return the same symbol, though I think `action_path` may
always be called with a symbol so this might not be necessary.
2015-08-10 17:57:17 -07:00
Aaron Patterson
f727bd24c2 pull path conditional up
we only need to check for `path` once.
2015-08-10 17:57:17 -07:00
Aaron Patterson
e852daa697 pull defaults extraction up the stack.
Now we can see where `defaults` options originate
2015-08-10 15:31:33 -07:00
Aaron Patterson
7c6c048f97 avoid calling scope on defaults methods 2015-08-10 15:20:33 -07:00
Aaron Patterson
d193b3bbf6 let the controller method push / pop the stack
since `controller` and `controller_scope` were the same, just combine
them
2015-08-10 14:39:33 -07:00
Aaron Patterson
ae3269b79b remove another call to scope 2015-08-10 14:36:59 -07:00
Aaron Patterson
628a23cdd2 remove dead code
This method isn't used internally, isn't tested, isn't documented.  We
should delete it.
2015-08-10 14:31:29 -07:00
Aaron Patterson
6ac882bb58 avoid is_a? calls
add a predicate method so that we can avoid is_a? calls on the resource
object.
2015-08-10 13:36:17 -07:00
Aaron Patterson
3c8775349c avoid another call to scope
calling `scope` isn't cheap, so try to call cheaper methods that do the
same thing for those particular parameters (in this case `path_scope`)
2015-08-10 13:30:31 -07:00
Aaron Patterson
6bc8ada05c push with_scope_level up so resource_scope doesn't know
`resource_scope` should just put resource scopes on the stack, and
doesn't need to know what a `scope_level` is.
2015-08-10 13:24:35 -07:00
Aaron Patterson
d4e1a75918 reuse the same frame so we don't need a singleton hash
We just want to augment the scope level, not the frame itself, so just
copy the frame to the new scope object.
2015-08-10 13:24:35 -07:00
Aaron Patterson
8e014f28cc add a null node at the top of the stack
this gives us an easier way to iterate the stack
2015-08-10 12:35:57 -07:00
Aaron Patterson
53454bfcb6 remove @nesting ivar
The same information is stored in the `@scope` linked list, so just get
it from there.
2015-08-10 12:16:49 -07:00
Aaron Patterson
d9603cb09f pass shallow in to the resource constructor
this lets us remove the setter and make the Resource object Read-Only
2015-08-10 11:51:24 -07:00
Aaron Patterson
6a9d1925dc we have the resource on the stack, so just use it
We don't need to ask `scope` for the resource because we already have it
right here.
2015-08-10 11:39:41 -07:00
Rafael Mendonça França
8d0c107a60 Remove wrong comment
This method raises conditionally not always so we should not documment
as it always raise.
2015-08-09 23:30:08 -03:00
Rafael Mendonça França
09e1689252 Remove the conditional since it is done in the method 2015-08-09 23:27:40 -03:00
Rafael Mendonça França
20cf2dd089 Execute the block when the controller doesn't exist
We should return when the contoller key is not present or if the
controller doesn't exist and we didn't raised an error.
2015-08-09 23:15:35 -03:00
Rafael Mendonça França
4818fdd36b Name the argument according with its job
Related with dc1b937db780155089fce522f03d340e62f5df36
2015-08-09 23:10:48 -03:00
Aaron Patterson
919e7d3e6c push scope calls up one frame
eliminates calling `scope` in one method, pushes the other calls up one
frame.  This goes a little way towards eliminating the internal calls to
`scope`.
2015-08-09 17:11:43 -07:00
Aaron Patterson
378e3a666e remove useless hash
we don't really need this hash.
2015-08-08 18:57:47 -07:00
Aaron Patterson
f360689586 stop calling scope internally
we need to get a grip on what `scope` actually does.  This commit
removes some of the internal calls to `scope`.  Eventually we should add
public facing methods that provide the API that `scope` is trying to
accomplish.
2015-08-08 18:48:27 -07:00
Aaron Patterson
5a18b853ed remove useless conditional
`prepare_params!` would raise an exception if `params` wasn't
initialized, so it must always be available.  Remove the existence
conditional from the `controller` method.
2015-08-08 17:12:50 -07:00
Aaron Patterson
1b73d53a1c eliminate assignment in conditional
The method we called already has the conditional we need.  Just add an
else block so that we don't need two tests.
2015-08-08 16:39:16 -07:00
Aaron Patterson
dc1b937db7 Remove defaults hash from Dispatcher
`Dispatcher` doesn't need to hold on to the defaults hash.  It only used
the hash to determine whether or not it should raise an exception if
there is a name error.  We can pass that in further up the stack and
alleviate Dispatcher from knowing about that hash.
2015-08-08 16:34:34 -07:00
Aaron Patterson
175e92c9ac eliminate runtime conditional
We know in advance whether the object is a dispatcher or not, so we can
configure the Constraints object with a strategy that will call the
right method.
2015-08-08 16:12:00 -07:00
Aaron Patterson
246bfcb473 whitespace 2015-08-08 15:41:36 -07:00
Aaron Patterson
5e81e6ca31 remove the setter from Scope
it isn't used.
2015-08-08 15:04:20 -07:00
Kasper Timm Hansen
3a7609e2ba Merge pull request #21167 from AaronLasseigne/use_each_key
replace each with each_key when only the key is needed
2015-08-08 18:56:10 +02:00
Aaron Lasseigne
725f9bf3e2 replace each with each_key when only the key is needed
Using each_key is faster and more intention revealing.

Calculating -------------------------------------
                each    31.378k i/100ms
            each_key    33.790k i/100ms
-------------------------------------------------
                each    450.225k (± 7.0%) i/s -      2.259M
            each_key    494.459k (± 6.3%) i/s -      2.467M

Comparison:
            each_key:   494459.4 i/s
                each:   450225.1 i/s - 1.10x slower
2015-08-08 11:54:09 -05:00
eileencodes
286cb890de Refactor route assertion methods in resources test
The tests and methods were hard to read with `options[:options]` all
over the place. This refactoring makes the code easier to understand.

The change came out of work for moving the underlying code of controller
tests to integraiton tests.
2015-08-08 11:53:05 -04:00
Rafael Mendonça França
d919fd88ec Merge pull request #11352 from xaviershay/dispatcher-api
Allow a custom dispatcher to be provided to routing.
2015-08-08 12:22:21 -03:00
eileencodes
12f08acbac Fix deprecation warning in tests
Using the string version of the class reference is now deprecated when
referencing middleware. This should be written as a class not as a string.

Deprecation warning that this change fixes:
```
DEPRECATION WARNING: Passing strings or symbols to the middleware
builder is deprecated, please change
them to actual class references.  For example:
  "ActionDispatch::ShowExceptions" => ActionDispatch::ShowExceptions
```
2015-08-08 10:38:09 -04:00
eileencodes
e7dd9069ca Rename extra_keys variables to query_string_keys
`extra_keys` is a confusing variable name because it's not clear what is
"extra". This renames it to `query_string_keys` so it's clear that the
"extra" is just the query string.
2015-08-08 10:29:34 -04:00
eileencodes
c8b8295583 Refactor to remove DrawOnce module
We were doing extra work that could be pushed off to Integration test
and SharedRoutes. Creating an extra module isn't necessary when those
are created by their respective classes.
2015-08-08 10:15:35 -04:00
Xavier Shay
2992b1c04c Allow a custom dispatcher to be provided to routing. 2015-08-07 20:06:24 -07:00
Xavier Shay
f26ae7d10f Move controller_reference and controller_class_names to protected
scope so that they are available to subclasses.
2015-08-07 19:50:14 -07:00
Aaron Patterson
05934d24af deprecate the env method on controller instances
people should be accessing request information through the request
object, not via the env hash.  If they really really want at the env
hash, then they can get it off the request.
2015-08-07 16:27:32 -07:00
Aaron Patterson
869b007172 the request object manages env
remove the setter.  The request object manages the env hash, so any
mutations need to go through it
2015-08-07 16:20:38 -07:00
Aaron Patterson
1f80f3a373 remove vestigial code
Looks like this was left over from converting Rails to Rack.  I think
it's safe to remove now.
2015-08-07 16:17:22 -07:00
Aaron Patterson
81cfdf2489 stop using @_env in the controller instance
Actions are processed through `dispatch`, so they should have the
request set on them before any user land code can be executed.  Lets
stop setting _env on the controller, and give access to it through the
`env` method.
2015-08-07 16:00:57 -07:00
Aaron Patterson
2a3c47ff5d finish deprecating handling strings and symbols
since we only work with instances of classes, it greatly simplifies the
`Middleware` implementation.
2015-08-07 15:37:31 -07:00
Aaron Patterson
83b767cef9 Using strings or symbols for middleware class names is deprecated.
Convert things like this:

  middleware.use "Foo::Bar"

to this:

  middleware.use Foo::Bar
2015-08-07 15:37:31 -07:00
Aaron Patterson
435b224e7e move valid? conditional to the constructor
use a strategy pattern to calculate the conditional in `valid?` in
advance.
2015-08-07 15:37:31 -07:00
Aaron Patterson
27eddbb332 simplify the Middleware constructor
We should do the hard work outside the constructor.  Also fix the tests
to not directly construct middleware objects, but to go through the
stack object.
2015-08-07 15:37:31 -07:00
Aaron Patterson
e4f9a0b925 use Proc.new to reduce some conditionals
Proc.new will pick up the passed in block, but since it's a default
param, it won't get evaluated unless someone doesn't pass in an app.  It
will raise an exception if no block is provided.
2015-08-07 15:37:31 -07:00
Aaron Patterson
4485351501 the request class is never changed, so just use it directly in the method body 2015-08-07 15:37:31 -07:00
Aaron Patterson
9b7ecf0d6d refactor param parsing middleware to use request objects
this is another place that we should stop directly accessing the env
hash and let the request object take care of that for us
2015-08-07 07:55:19 -07:00
Aaron Patterson
85969c74cd move flash hash access to methods on the request object 2015-08-07 07:55:19 -07:00
Rafael Mendonça França
3fb5cd4d40 Merge pull request #21153 from grosser/grosser/ports
do not add common ports to HTTP_HOST
2015-08-06 22:42:45 -03:00
Gabriel Sobrinho
8329de22cd Fix documentation on ActionDispatch::Request 2015-08-06 22:12:45 -03:00
Michael Grosser
a278630f5f do not add common ports to HTTP_HOST
- webservers do not do it
 - it makes redirect urls ugly when request.host is used for redirection
2015-08-06 17:33:32 -07:00
Aaron Patterson
07b2ff03d0 use a request object to access info from env in GetIp
again, we want to hide the contents of `env` from the implementation.
Allocate a request object to access the contents of env, but save
allocations due to string literal allocations when accessing the env
hash.
2015-08-06 16:20:47 -07:00
Aaron Patterson
6716ad555a ask the request if we should show exceptions
hide the env key in the request object so that other code doesn't need
to know.
2015-08-06 16:12:06 -07:00
Aaron Patterson
6d85804bc6 ExceptionWrapper doesn't need to know about env
ExceptionWrapper only cares about the backtrace cleaner, so lets just
pass the cleaner to the wrapper.  It does not need to know that env
exists or what key the backtrace cleaner is stored in
2015-08-06 15:59:44 -07:00
Aaron Patterson
38251d2e33 prevent string allocations 2015-08-06 15:59:44 -07:00
Aaron Patterson
6caeec53d5 reuse the request object in the File serving middleware
Implement `serve` on the middleware.  Nothing can be placed between the
instance of FileHandler and Static because Static instantiates an
instance of FileHandler.  IOW there is no reason to implement the `call`
API in this case.
2015-08-06 15:18:35 -07:00
Aaron Patterson
595bef5df8 get the underlying REQUEST_METHOD from the superclass 2015-08-06 15:13:07 -07:00
Aaron Patterson
8f27d6036a use a request object to reduce string allocations and not know about ENV keys 2015-08-06 15:12:19 -07:00
Rafael Mendonça França
1b9ecef358 Merge pull request #21061 from yui-knk/refactor/route_set
Remove duplicated `Array#to_param`
2015-08-06 17:27:42 -03:00
Rafael Mendonça França
19d46e849e Merge pull request #21131 from eagletmt/percent-filename
Fix Encoding::UndefinedConversionError with multibyte UTF-8 filename containing "%" character
2015-08-06 17:20:59 -03:00
Matthew Gerrior
3004cc8177 Adds missing argument handling for ActionController::TestSession to
allow testing controllers that use session#fetch with a default value.
2015-08-06 15:29:45 -04:00
Aaron Patterson
3908a6d867 remove dead code
we don't recycle requests anymore, so we shouldn't need to recycle
cookie jars
2015-08-06 08:00:19 -07:00
Aaron Patterson
1989b20c16 ask the request for the cookie jar
this prevents the middleware from knowing the specific key for the jar
2015-08-06 07:57:33 -07:00
Aaron Patterson
447c2cb1b0 add a setter for the cookie jar 2015-08-06 07:54:47 -07:00
Aaron Patterson
e18ebd2e62 remove request reference from chained jars
This changes the chained jars to ask the parent jar for the request
object which should eventually call back up to the original jar
2015-08-06 07:42:38 -07:00
Aaron Patterson
3d32a50ca1 remove @host ivar 2015-08-05 18:17:13 -07:00
Aaron Patterson
aad33d5808 remove @secure ivar 2015-08-05 18:15:08 -07:00
Aaron Patterson
78960cf560 CookieJar does not need the key_generator parameter anymore 2015-08-05 18:09:55 -07:00
Aaron Patterson
197141a8c7 eliminate key_generator ivar 2015-08-05 18:08:05 -07:00
Aaron Patterson
de6b43bfd1 sop passing host and secure to the build method
eventually we will make the cookie jar derive these values from the
request object rather than save a reference to the values
2015-08-05 17:59:28 -07:00
Aaron Patterson
e6074a3541 stop using an options hash with the cookie jar
The cookie jar can just ask the request object for the information it
needs.  This allows us to stop allocating hashes for options, and also
allows us to delay calculating values in advance.  Generating the
options hash forced us to calculate values that we may never have needed
at runtime
2015-08-05 17:40:28 -07:00
Aaron Patterson
de59e6ebad move env access to the request object.
Accessing a request object has nice advantages over accessing a hash.
If you use a missing method name, you'll get an exception rather than a
`nil` (is one nice feature)
2015-08-05 17:24:48 -07:00
Aaron Patterson
a31bfe6983 routes in the env via the request object 2015-08-05 17:13:19 -07:00
Aaron Patterson
df71e48be8 allocate a request object to avoid hash allocations
This decouples the `call` method from knowing the SCRIPT_NAME key and
offloads decisions about how to access script_name
2015-08-05 16:55:03 -07:00
Kohei Suzuki
9521e18ed0 Assume uploaded filename is UTF-8 2015-08-05 20:24:58 +09:00
Kohei Suzuki
b5ae1be2cd Add failing spec on utf8 filename with percent character 2015-08-04 21:27:22 +09:00
Yves Senn
c402479f59 Merge pull request #21095 from aditya-kapoor/add-missing-assertion
Add missing assertion for test_route_with_colon_first
2015-08-03 10:51:34 +02:00
Aditya Kapoor
7481039225 Add missing assertion for test_route_with_colon_first 2015-08-03 13:48:15 +05:30
amitkumarsuroliya
eb55bd3430 Remove duplicity in tests 2015-08-03 12:31:19 +05:30
Benjamin Quorning
113f8a6cc9 Use #start_with? and #[] for speed
While the readability may be slightly worse, the speed improvement is
significant: Twice as fast when there's no leading "/" to remove, and
over 4 times as fast when there is a leading "/".

Benchmark:

    require 'benchmark/ips'

    def match(controller)
      if controller
        if m = controller.match(/\A\/(?<controller_without_leading_slash>.*)/)
          m[:controller_without_leading_slash]
        else
          controller
        end
      end
    end

    def start_with(controller)
      if controller
        if controller.start_with?('/'.freeze)
          controller[1..-1]
        else
          controller
        end
      end
    end

    Benchmark.ips do |x|
      x.report("match") { match("no_leading_slash") }
      x.report("start_with") { start_with("no_leading_slash") }

      x.compare!
    end

    Benchmark.ips do |x|
      x.report("match") { match("/a_leading_slash") }
      x.report("start_with") { start_with("/a_leading_slash") }

      x.compare!
    end

Result (Ruby 2.2.2):

    Calculating -------------------------------------
                   match    70.324k i/100ms
              start_with   111.264k i/100ms
    -------------------------------------------------
                   match      1.468M (± 7.1%) i/s -      7.314M
              start_with      3.787M (± 3.5%) i/s -     18.915M

    Comparison:
              start_with:  3787389.4 i/s
                   match:  1467636.4 i/s - 2.58x slower

    Calculating -------------------------------------
                   match    36.694k i/100ms
              start_with    86.071k i/100ms
    -------------------------------------------------
                   match    532.795k (± 4.7%) i/s -      2.679M
              start_with      2.518M (± 5.8%) i/s -     12.566M

    Comparison:
              start_with:  2518366.8 i/s
                   match:   532794.5 i/s - 4.73x slower
2015-08-02 13:21:27 +02:00
Aditya Kapoor
854ab2e1e6 add missing tests for action regexp 2015-08-02 13:39:40 +05:30
Richard Schneeman
c7a9f572d1 Merge pull request #21088 from yui-knk/doc/to_param
[ci skip]
2015-08-01 09:42:31 -05:00
yui-knk
2ea95a522a [ci skip]
Add descriptions about `ActiveRecord::Base#to_param` to

* `ActionDispatch::Routing::Base#match`
* Overriding Named Route Parameters (guide)

When passes `:param` to route definision, always `to_param` method of
related model is overridden to constructe an URL by passing these
model instance to named_helper.
2015-08-01 23:08:53 +09:00
Yves Senn
21b870c906 docs, custom api base controllers shoudl subclass metal. [ci skip]
This is a follow up to #21008.
2015-08-01 12:20:20 +02:00
Yves Senn
7c03190344 Merge pull request #21008 from svenwin/patch-1
Add documentation to get a running custom base controller [ci skip]
2015-08-01 12:19:09 +02:00
yui-knk
0069965a84 Remove duplicated Array#to_param
`Array#to_param` is defind in active_support/core_ext/object/to_query.rb,
so we can call `to_param` if value is_a Array.
2015-08-01 19:08:06 +09:00
Jean Boussier
32133db710 Array#any? is slower and not the inverse of Array#empty?
```
empty_array = []
small_array = [1] * 30
bigger_array = [1] * 300

Benchmark.ips do |x|
  x.report('empty !empty?') { !empty_array.empty? }
  x.report('small !empty?') { !small_array.empty? }
  x.report('bigger !empty?') { !bigger_array.empty? }

  x.report('empty any?') { empty_array.any? }
  x.report('small any?') { small_array.any? }
  x.report('bigger any?') { bigger_array.any? }
end
```

```
Calculating -------------------------------------
       empty !empty?   132.059k i/100ms
       small !empty?   133.974k i/100ms
      bigger !empty?   133.848k i/100ms
          empty any?   106.924k i/100ms
          small any?    85.525k i/100ms
         bigger any?    86.663k i/100ms
-------------------------------------------------
       empty !empty?      8.522M (± 7.9%) i/s -     42.391M
       small !empty?      8.501M (± 8.5%) i/s -     42.202M
      bigger !empty?      8.434M (± 8.6%) i/s -     41.894M
          empty any?      4.161M (± 8.3%) i/s -     20.743M
          small any?      2.654M (± 5.2%) i/s -     13.256M
         bigger any?      2.642M (± 6.4%) i/s -     13.173M
```

Ref: https://github.com/rails/rails/pull/21057#discussion_r35902468
2015-07-30 15:12:37 -04:00
schneems
22f5924014 Use delete_if instead of each; delete(key)
It is slightly faster:

```
Calculating -------------------------------------
        each; delete    35.166k i/100ms
           delete_if    36.416k i/100ms
-------------------------------------------------
        each; delete    478.026k (± 8.5%) i/s -      2.391M
           delete_if    485.123k (± 7.9%) i/s -      2.440M
```
2015-07-30 12:34:48 -05:00
schneems
61dae88254 Remove (another) array allocation
We don't always need an array when generating a url with the formatter. We can be lazy about allocating the `missing_keys` array. This saves us:

35,606 bytes and 889 objects per request
2015-07-30 12:31:05 -05:00
schneems
4d2ccc119c Remove array allocation
THe only reason we were allocating an array is to get the "missing_keys" variable in scope of the error message generator. Guess what? Arrays kinda take up a lot of memory, so by replacing that with a nil, we save:

35,303 bytes and 886 objects per request
2015-07-30 12:31:05 -05:00
schneems
1993e2ccbd Avoid hash duplication by skipping mutation
If we don't mutate the `recall` hash, then there's no reason to duplicate it. While this change doesn't get rid of that many objects, each hash object it gets rid of was massive.

Saves 888 string objects per request, 206,013 bytes (thats 0.2 mb which is kinda a lot).
2015-07-30 12:31:04 -05:00
schneems
3fb9e80243 Only allocate new string when needed
Instead of calling `sub` on every link_to call for controller, we can detect when the string __needs__ to be allocated and only then create a new string (without the leading slash), otherwise, use the string that is given to us.

Saves 888 string objects per request, 35,524 bytes.
2015-07-30 12:31:04 -05:00
schneems
045cdd3a3d Freeze a string in comparator
Saves 888 string objects per request.
2015-07-30 12:31:04 -05:00
schneems
bff61ba27c Avoid calling to_s on nil in journey/formatter
When `defaults[key]` in `generate` in the journey formatter is called, it often returns a `nil` when we call `to_s` on a nil, it allocates an empty string. We can skip this check when the default value is nil.

This change buys us 35,431 bytes of memory and 887 fewer objects per request.

Thanks to @matthewd for help with the readability
2015-07-30 12:30:47 -05:00
schneems
1a14074fb5 Reduce hash allocations in route_set
When generating a url with `url_for` the hash of arguments passed in, is dup-d and merged a TON. I wish I could clean this up better, and might be able to do it in the future. This change removes one dup, since it's literally right after we just dup-d the hash to pass into this constructor.

This may be a breaking, change but the tests pass...so :shipit: we can revert if it causes problems

This change buys us 205,933 bytes of memory and 887 fewer objects per request.
2015-07-29 20:41:57 -05:00
schneems
0cbec58ae4 Decrease route_set allocations
In handle_positional_args `Array#-=` is used which allocates a new array. Instead we can iterate through and delete elements, modifying the array in place.

Also `Array#take` allocates a new array. We can build the same by iterating over the other element.

This change buys us 106,470 bytes of memory and 2,663 fewer objects per request.
2015-07-29 20:41:57 -05:00
schneems
097ec6fb7c Speed up journey missing_keys
Most routes have a `route.path.requirements[key]` of `/[-_.a-zA-Z0-9]+\/[-_.a-zA-Z0-9]+/` yet every time this method is called a new regex is generated on the fly with `/\A#{DEFAULT_INPUT}\Z/`. OBJECT ALLOCATIONS BLERG!

This change uses a special module that implements `===` so it can be used in a case statement to pull out the default input. When this happens, we use a pre-generated regex.

This change buys us 1,643,465 bytes of memory and 7,990 fewer objects per request.
2015-07-29 20:41:57 -05:00
schneems
9b8258814e Speed up journey extract_parameterized_parts
Micro optimization: `reverse.drop_while` is slower than `reverse_each.drop_while`. This doesn't save any object allocations.

Second, `keys_to_keep` is typically a very small array. The operation `parameterized_parts.keys - keys_to_keep` actually allocates two arrays. It is quicker (I benchmarked) to iterate over each and check inclusion in array manually.

This change buys us 1774 fewer objects per request
2015-07-29 20:41:57 -05:00
schneems
83ee043c68 Decrease string allocations in url_options
The request.script_name is dup-d which allocates an extra string. It is most commonly an empty string "". We can save a ton of string allocations by checking first if the string is empty, if so we can use a frozen empty string instead of duplicating an empty string.

This change buys us 35,714 bytes of memory and 893 fewer objects per request.
2015-07-29 20:41:57 -05:00
Robin Dupret
e18bf1dc49 Tiny documentation edits [ci skip] 2015-07-28 15:05:41 +02:00
Robin Dupret
a74fbb2972 Add :nodoc: for internal testing methods [ci skip] 2015-07-28 12:22:37 +02:00
Rafael Mendonça França
32b0db266c Merge pull request #20590 from vngrs/set_default_charset
Document, refactor and create test case for ActionDispatch::Response
2015-07-27 17:31:24 -03:00
Rafael Mendonça França
f9a02c45fa Merge pull request #21031 from vngrs/fix_params_wrapper_doc
Fix params_wrapper doc [ci skip]
2015-07-27 16:55:47 -03:00
Aditya Kapoor
b4db53fad4 [ci skip] it should be protect_from_forgery 2015-07-27 21:31:12 +05:30
Mehmet Emin İNAÇ
edda07b2ce Fix params_wrapper doc [ci skip]
This feature also works with `PUT`, `PATCH` and `DELETE` requests.
Also developers can add `:url_encoded_form` and `:multipart_form`
into the `:format` for wrapping url encoded or multipart form data.
2015-07-26 07:18:40 +03:00
Sven Winkler
7c5e4227d1 Add documentation to get a running custom base controller [ci skip] 2015-07-23 23:55:35 +02:00
Aaron Patterson
52cf1a71b3 rm deep_munge. You will live on in our hearts (and git history)
Now that we have encoding strategies, we can just walk the params hash
once to encode as HWIA, and remove nils.
2015-07-21 18:14:18 -07:00
Aaron Patterson
3f299296d1 push param encoding in to the utils module
we'll refactor deep munge mostly out of existence shortly
2015-07-21 18:04:12 -07:00
Aaron Patterson
f620d6c25e stop keeping track of keys when "deep munging"
This should have been done along with 8f8ccb9901cab457c6e1d52bdb25acf658fd5777
2015-07-21 17:57:50 -07:00
Aaron Patterson
14e8377232 recurse for arrays in normalize_encode_params
this just pushes the conditional in to the case / when so we can switch
to method dispatch later
2015-07-21 17:49:30 -07:00
Aaron Patterson
5046d5179e drop conditionals in conversion logic
there is no reason to `convert_hashes_to_parameters` with an assignemt
flag.  The caller knows whether or not it wants the value assigned.  We
should just change the uncommon case (not writing to the underlying
hash) to just call the conversion method and return that value.
2015-07-21 15:10:14 -07:00
Aaron Patterson
c75153d280 rearrange logic to use positive branches
only hashes are converted to parameter objects, so lets add a branch for
them.  This also removes a is_a? test for Parameters so we can be
abstracted from the class.
2015-07-21 15:04:19 -07:00
Rafael Mendonça França
8ff777f6f8 Merge pull request #20751 from repinel/remove-unnecessary-dup
Remove unnecessary `dup` from Mapper `add_route`
2015-07-20 23:40:54 -03:00
Roque Pinel
12b0b26df7 Fix state being carried over from previous transaction
This clears the transaction record state when the transaction finishes
with a `:committed` status.

Considering the following example where `name` is a required attribute.
Before we had `new_record?` returning `true` for a persisted record:

```ruby
  author = Author.create! name: 'foo'
  author.name = nil
  author.save        # => false
  author.new_record? # => true
```
2015-07-20 09:12:01 -06:00
Sean Griffin
f91439d848 Merge pull request #20946 from schneems/schneems/let-it-go
Freeze string literals when not mutated.
2015-07-19 17:09:13 -06:00
schneems
5bb1d4d288 Freeze string literals when not mutated.
I wrote a utility that helps find areas where you could optimize your program using a frozen string instead of a string literal, it's called [let_it_go](https://github.com/schneems/let_it_go). After going through the output and adding `.freeze` I was able to eliminate the creation of 1,114 string objects on EVERY request to [codetriage](codetriage.com). How does this impact execution?

To look at memory:

```ruby
require 'get_process_mem'

mem = GetProcessMem.new
GC.start
GC.disable
1_114.times { " " }
before = mem.mb

after = mem.mb
GC.enable
puts "Diff: #{after - before} mb"

```

Creating 1,114 string objects results in `Diff: 0.03125 mb` of RAM allocated on every request. Or 1mb every 32 requests.

To look at raw speed:

```ruby
require 'benchmark/ips'

number_of_objects_reduced = 1_114

Benchmark.ips do |x|
  x.report("freeze")    { number_of_objects_reduced.times { " ".freeze } }
  x.report("no-freeze") { number_of_objects_reduced.times { " " } }
end
```

We get the results

```
Calculating -------------------------------------
              freeze     1.428k i/100ms
           no-freeze   609.000  i/100ms
-------------------------------------------------
              freeze     14.363k (± 8.5%) i/s -     71.400k
           no-freeze      6.084k (± 8.1%) i/s -     30.450k
```

Now we can do some maths:

```ruby
ips = 6_226k # iterations / 1 second
call_time_before = 1.0 / ips # seconds per iteration 

ips = 15_254 # iterations / 1 second
call_time_after = 1.0 / ips # seconds per iteration 

diff = call_time_before - call_time_after

number_of_objects_reduced * diff * 100

# => 0.4530373333993266 miliseconds saved per request
```

So we're shaving off 1 second of execution time for every 220 requests. 

Is this going to be an insane speed boost to any Rails app: nope. Should we merge it: yep. 

p.s. If you know of a method call that doesn't modify a string input such as [String#gsub](b0e2da69f0/lib/let_it_go/core_ext/string.rb (L37)) please [give me a pull request to the appropriate file](b0e2da69f0/lib/let_it_go/core_ext/string.rb (L37)), or open an issue in LetItGo so we can track and freeze more strings. 

Keep those strings Frozen

![](https://www.dropbox.com/s/z4dj9fdsv213r4v/let-it-go.gif?dl=1)
2015-07-19 17:45:10 -05:00
Sean Griffin
e19acbb883 Merge pull request #20936 from repinel/fix-params-fetch-exception-overwritten
Fix exception overwritten for parameters fetch method
2015-07-19 15:57:57 -06:00
Eliot Sykes
2dcd0016e8 Fix formatting of force_ssl options documentation [ci skip] 2015-07-19 10:18:01 +01:00
Roque Pinel
780af27bf9 Fix exception overwritten for parameters fetch method
When executing an `ActionController::Parameters#fetch` with a block
that raises a `KeyError` the raised `KeyError` will be rescued and
converted to an `ActionController::ParameterMissing` exception,
covering up the original exception.

[Jonas Schubert Erlandsson & Roque Pinel]
2015-07-18 18:48:41 -04:00
Prem Sichanugrist
8cb8ce98d9 Stop using deprecated render :text in test
This will silence deprecation warnings.

Most of the test can be changed from `render :text` to render `:plain`
or `render :body` right away. However, there are some tests that needed
to be fixed by hand as they actually assert the default Content-Type
returned from `render :body`.
2015-07-17 22:27:33 -04:00
Jeremy Daer (Kemper)
0db98b3ec8 Merge pull request #20917 from sikachu/ps-deprecate-render-text
Add deprecation warning for `render :text`
2015-07-17 18:17:47 -07:00
Prem Sichanugrist
6790228b39 Add deprecation warning for render :text
We've started on discouraging the usage of `render :text` in #12374.
This is a follow-up commit to make sure that we print out the
deprecation warning.
2015-07-17 21:12:47 -04:00
Aaron Patterson
0fedae636e push fields_for_style? in to a protected method
this way we don't need to call `to_unsafe_h` to get access to ask
questions about the underlying hash
2015-07-17 14:43:06 -07:00
Aaron Patterson
e956172b8b push is_a checks up the stack
now `hash_filter` doesn't need to know about the `Parameters` class
2015-07-17 14:26:47 -07:00
Aaron Patterson
7779e63371 remove useless conditional
Since we proved that `element` is always of type `Parameter`, we know
that it will always respond to `permit`, so lets remove this conditional
2015-07-17 14:18:47 -07:00
Aaron Patterson
89448a7f5c remove useless conditionals
`element` can never be a hash because:

1. `slice` returns a Parameters object and calls each on it: cb3f25593b/actionpack/lib/action_controller/metal/strong_parameters.rb (L656)
2. `each` which is implemented by `each_pair` will call `convert_hashes_to_parameters` on the value: cb3f25593b/actionpack/lib/action_controller/metal/strong_parameters.rb (L192-197)
3. `convert_hashes_to_parameters` will convert any hash objects in to parameters objects: cb3f25593b/actionpack/lib/action_controller/metal/strong_parameters.rb (L550-566)
2015-07-17 14:08:12 -07:00
Aaron Patterson
cb3f25593b remove useless function
Now that the value is cached on the stack,
`array_of_permitted_scalars_filter` is exactly the same as
`array_of_permitted_scalars?`, so lets just have one
2015-07-17 13:36:33 -07:00
Aaron Patterson
2df8e86caf stop passing params to array_of_permitted_scalars_filter
this way the method doesn't have to know what the new params object is,
it just yields to a block.  This change also caches the value of
`self[key]` on the stack
2015-07-17 13:36:33 -07:00
Aaron Patterson
55d0e6f877 push key checking up
We should disconnect `array_of_permitted_scalars_filter` from the
instance so that we can make hash filtering functional.  For now, pull
the conditional up out of that method
2015-07-17 13:36:33 -07:00
Jon Atack
ea747f7d2e [skip ci] Lookup can be a noun but it is not a verb
Various grammar corrections and wrap to 80 characters.
2015-07-17 20:18:57 +02:00
Robin Dupret
ae1b96cfcd Skip a few failing tests on JRuby with the attached tickets 2015-07-17 15:00:00 +02:00
Akira Matsuda
022c676aee Oops! 💣 2015-07-17 18:31:59 +09:00
Akira Matsuda
8b3c68399f "warning: instance variable @routes not initialized" 2015-07-17 18:29:52 +09:00
Zoltan Kiss
ea6e7ffd78 Standardize ActionController::Parameters#to_unsafe_h return value
`ActionController::Parameters#to_h` returns a hash, so lets have
`ActionController::Parameters#to_unsafe_h` return a hash instead of
an `ActiveSupport::HashWithIndifferentAccess` for consistency.
2015-07-15 19:20:21 -05:00
Prem Sichanugrist
84b861f1aa Update documentation on AC::Parameters 2015-07-15 13:02:53 -04:00
Prem Sichanugrist
14a3bd520d Make AC::Parameters not inherited from Hash
This is another take at #14384 as we decided to wait until `master` is
targeting Rails 5.0. This commit is implementation-complete, as it
guarantees that all the public methods on the hash-inherited Parameters
are still working (based on test case). We can decide to follow-up later
if we want to remove some methods out from Parameters.
2015-07-15 11:11:36 -04:00
Aaron Patterson
4d4d764ab6 Rack implements redirect? so we don't need it
Rack [already implements `redirect?` on the response object](1569a985e1/lib/rack/response.rb (L141)) so we don't need to implement our own.
2015-07-14 11:22:35 -07:00
Rafael Mendonça França
8aadbeb3de Remove concurrent-ruby from Action Pack gemspec
It is already on Active Support
2015-07-14 15:17:41 -03:00
Aaron Patterson
468a55b741 Merge pull request #20866 from jdantonio/countdown-latch
Replace `ActiveSupport::Concurrency::Latch` with `Concurrent::CountDownLatch` from concurrent-ruby.
2015-07-14 11:06:20 -07:00
Rafael Mendonça França
7645a5f85d Merge pull request #20877 from sikachu/rename-ac-test_response
Change AC::TestResponse to AD::TestResponse
2015-07-14 12:26:30 -03:00