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

Implement helpers proxy in controller instance level

It is a common pattern in the Rails community that when people want to
:xa
use any kind of helper that is defined inside app/helpers they includes
the helper module inside the controller like:

    module UserHelper
      def my_user_helper
        # ...
      end
    end

    class UsersController < ApplicationController
      include UserHelper

      def index
        render inline: my_user_helper
      end
    end

This has problem because the helper can't access anything that is
defined in the view level context class.

Also all public methods of the helper become available in the controller
what can lead to undesirable methods being routed and behaving as
actions.

Also if you helper depends on other helpers or even Action View helpers
you need to include each one of these dependencies in your controller
otherwise your helper is not going to work.

We already have a helpers proxy at controller class level but that proxy
doesn't have access to the instance variables defined in the
controller.

With this new instance level helper proxy users can reuse helpers in the
controller without having to include the modules and with access to
instance variables defined in the controller.

    class UsersController < ApplicationController
      def index
        render inline: helpers.my_user_helper
      end
    end
This commit is contained in:
Rafael Mendonça França 2016-05-05 12:02:28 -05:00
parent cece50d3a6
commit 541a51ecf8
4 changed files with 29 additions and 2 deletions

View file

@ -1,3 +1,9 @@
* Add `ActionController#helpers` to get access to the view context in the controller
level.
*Rafael Mendonça França*
## Rails 5.0.0.beta4 (April 27, 2016) ##
* Routing: Refactor `:action` default handling to ensure that path

View file

@ -253,7 +253,7 @@ module ActionController
# Define some internal variables that should not be propagated to the view.
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + %i(
@_params @_response @_request @_config @_url_options @_action_has_layout @_view_context_class
@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime
@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
)
def _protected_ivars # :nodoc:

View file

@ -5,7 +5,7 @@ module ActionController
#
# In addition to using the standard template helpers provided, creating custom helpers to
# extract complicated logic or reusable functionality is strongly encouraged. By default, each controller
# will include all helpers. These helpers are only accessible on the controller through <tt>.helpers</tt>
# will include all helpers. These helpers are only accessible on the controller through <tt>#helpers</tt>
#
# In previous versions of \Rails the controller will include a helper which
# matches the name of the controller, e.g., <tt>MyController</tt> will automatically
@ -113,5 +113,10 @@ module ActionController
all_helpers_from_path(helpers_path)
end
end
# Provides a proxy to access helpers methods from outside the view.
def helpers
@_helper_proxy ||= view_context
end
end
end

View file

@ -207,6 +207,22 @@ class HelperTest < ActiveSupport::TestCase
assert methods.include?(:foobar)
end
def test_helper_proxy_in_instance
methods = AllHelpersController.new.helpers.methods
# Action View
assert_includes methods, :pluralize
# abc_helper.rb
assert_includes methods, :bare_a
# fun/games_helper.rb
assert_includes methods, :stratego
# fun/pdf_helper.rb
assert_includes methods, :foobar
end
def test_helper_proxy_config
AllHelpersController.config.my_var = 'smth'