1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Fix sorting of helpers from different paths

When more than one directory for helpers is provided to a controller, it
should preserver the order of directories. Given 2 paths:

    MyController.helpers_paths = ["dir1/helpers", "dir2/helpers"]

helpers from dir1 should be loaded first. Before this commit, all
helpers were mixed and then sorted alphabetically, which essentially
would require to rename helpers to get desired order.

This is a problem especially for engines, where you would like to be
able to predict accurately which engine helpers will load first.

(closes #6496)
This commit is contained in:
Piotr Sarnacki 2012-05-27 14:01:44 +02:00
parent 523d0f09e4
commit e4aaac1301
6 changed files with 57 additions and 2 deletions

View file

@ -1,5 +1,16 @@
## Rails 4.0.0 (unreleased) ##
* change a way of ordering helpers from several directories. Previously,
when loading helpers from multiple paths, all of the helpers files were
gathered into one array an then they were sorted. Helpers from different
directories should not be mixed before loading them to make loading more
predictable. The most common use case for such behavior is loading helpers
from engines. When you load helpers from application and engine Foo, in
that order, first rails will load all of the helpers from application,
sorted alphabetically and then it will do the same for Foo engine.
*Piotr Sarnacki*
* `truncate` now always returns an escaped HTMl-safe string. The option `:escape` can be used as
false to not escape the result.

View file

@ -95,9 +95,9 @@ module ActionController
helpers = []
Array(path).each do |_path|
extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
helpers += Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
names = Dir["#{_path}/**/*_helper.rb"].map { |file| file.sub(extract, '\1') }
helpers += names.sort
end
helpers.sort!
helpers.uniq!
helpers
end

View file

@ -46,12 +46,42 @@ end
class MeTooController < JustMeController
end
class HelpersPathsController < ActionController::Base
paths = ["helpers2_pack", "helpers1_pack"].map do |path|
File.join(File.expand_path('../../fixtures', __FILE__), path)
end
$:.unshift(*paths)
self.helpers_path = paths
helper :all
def index
render :inline => "<%= conflicting_helper %>"
end
end
module LocalAbcHelper
def a() end
def b() end
def c() end
end
class HelperPathsTest < ActiveSupport::TestCase
def setup
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_helpers_paths_priority
request = ActionController::TestRequest.new
responses = HelpersPathsController.action(:index).call(request.env)
# helpers1_pack was given as a second path, so pack1_helper should be
# included as the second one
assert_equal "pack1", responses.last.body
end
end
class HelperTest < ActiveSupport::TestCase
class TestController < ActionController::Base
attr_accessor :delegate_attr

View file

@ -0,0 +1,5 @@
module Pack1Helper
def conflicting_helper
"pack1"
end
end

View file

@ -0,0 +1,5 @@
module Pack2Helper
def conflicting_helper
"pack2"
end
end

View file

@ -46,6 +46,10 @@ h4(#action_pack4_0). ActionPack
Rails 4.0 changed how <tt>assert_generates</tt>, <tt>assert_recognizes</tt>, and <tt>assert_routing</tt> work. Now all these assertions raise <tt>Assertion</tt> instead of <tt>RoutingError</tt>.
h4(#helpers_order). Helpers loading order
The loading order of helpers from more than one directory has changed in Rails 4.0. Previously, helpers from all directories were gathered and then sorted alphabetically. After upgrade to Rails 4.0 helpers will preserve the order of loaded directories and will be sorted alphabetically only within each directory. Unless you explicitly use <tt>helpers_path</tt> parameter, this change will only impact the way of loading helpers from engines. If you rely on the fact that particular helper from engine loads before or after another helper from application or another engine, you should check if correct methods are available after upgrade. If you would like to change order in which engines are loaded, you can use <tt>config.railties_order=</tt> method.
h3. Upgrading from Rails 3.1 to Rails 3.2
If your application is currently on any version of Rails older than 3.1.x, you should upgrade to Rails 3.1 before attempting an update to Rails 3.2.