Allow for deep directory path for view templates.
Merge pull request #7912 from mrship/master

CacheDigests: Support templates in directories several levels deep
adding a test for b21f24d9807bd161af947cf0f0cc440c9adffb73
When executing permit with just a key that points to a hash, DO NOT allow all the hash

params.require(:person).permit(:projects_attributes) was returning
=> {"projects_attributes"=>{"0"=>{"name"=>"Project 1"}}}

When should return
=> {}

You should be doing ...
params.require(:person).permit(projects_attributes: :name)
to get just the projects attributes you want to allow
update AC::Parameters#permit documentation [ci skip]

bdd105d changes the behaviour of AC::Parameters#permit.
Merge pull request #7915 from frodsan/docs_permit

update AC::Parameters#permit documentation [ci skip]
Cleanup trailing whitespaces
Merge pull request #7917 from dfens/master

Cosmetic changes: remove trailing whitespaces from tests
Revert "Key the attributes hash with symbols"

This reverts commit 86c3dfbd47cb96af02daaa655963292b1a1b110e.

Conflicts:
	activerecord/lib/active_record/attribute_methods/read.rb

Reason: whilst this increased performance, it also presents a DoS risk
via memory exhaustion if users were allowing user input to dictate the
arguments of read/write_attribute. I will investigate alternative ways
to cut down on string allocations here.
Don't allocate new strings in compiled attribute methods

This improves memory and performance without having to use symbols which
present DoS problems. Thanks @headius and @tenderlove for the
suggestion.

Benchmark
---------

require 'active_record'
require 'benchmark/ips'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database:
':memory:')

class Post < ActiveRecord::Base
  connection.create_table :posts, force: true do |t|
    t.string :name
  end
end

post = Post.create name: 'omg'

Benchmark.ips do |r|
  r.report('Post.new')          { Post.new name: 'omg' }
  r.report('post.name')         { post.name }
  r.report('post.name=')        { post.name = 'omg' }
  r.report('Post.find(1).name') { Post.find(1).name }
end

Before
------

Calculating -------------------------------------
            Post.new      1419 i/100ms
           post.name      7538 i/100ms
          post.name=      3024 i/100ms
   Post.find(1).name       243 i/100ms
-------------------------------------------------
            Post.new    20637.6 (±12.7%) i/s -     102168 in   5.039578s
           post.name  1167897.7 (±18.2%) i/s -    5186144 in   4.983077s
          post.name=    64305.6 (±9.6%) i/s -     317520 in   4.998720s
   Post.find(1).name     2678.8 (±10.8%) i/s -      13365 in   5.051265s

After
-----

Calculating -------------------------------------
            Post.new      1431 i/100ms
           post.name      7790 i/100ms
          post.name=      3181 i/100ms
   Post.find(1).name       245 i/100ms
-------------------------------------------------
            Post.new    21308.8 (±12.2%) i/s -     105894 in   5.053879s
           post.name  1534103.8 (±2.1%) i/s -    7634200 in   4.979405s
          post.name=    67441.0 (±7.5%) i/s -     337186 in   5.037871s
   Post.find(1).name     2681.9 (±10.6%) i/s -      13475 in   5.084511s