# frozen_string_literal: truerequire"active_support/dependencies"require"active_support/core_ext/name_error"moduleAbstractControllermoduleHelpersextendActiveSupport::Concernincludeddoclass_attribute:_helper_methods,default: Array.new# This is here so that it is always higher in the inheritance chain than# the definition in lib/action_view/rendering.rbredefine_singleton_method(:_helpers)doif@_helpers||=nil@_helperselsesuperclass._helpersendendself._helpers=define_helpers_module(self)endclassMissingHelperError<LoadErrordefinitialize(error,path)@error=error@path="helpers/#{path}.rb"set_backtraceerror.backtraceif/^#{path}(\.rb)?$/.match?(error.path)super("Missing helper file helpers/%s.rb"%path)elseraiseerrorendendenddef_helpersself.class._helpersendmoduleClassMethods# When a class is inherited, wrap its helper module in a new module.# This ensures that the parent class's module can be changed# independently of the child class's.definherited(klass)# Inherited from parent by defaultklass._helpers=nilklass.class_eval{default_helper_module!}unlessklass.anonymous?superendattr_writer:_helpers# Declare a controller method as a helper. For example, the following# makes the +current_user+ and +logged_in?+ controller methods available# to the view:# class ApplicationController < ActionController::Base# helper_method :current_user, :logged_in?## private# def current_user# @current_user ||= User.find_by(id: session[:user])# end## def logged_in?# current_user != nil# end# end## In a view:# <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>## ==== Parameters# * <tt>method[, method]</tt> - A name or names of a method on the controller# to be made available on the view.defhelper_method(*methods)methods.flatten!self._helper_methods+=methodslocation=caller_locations(1,1).firstfile,line=location.path,location.linenomethods.eachdo|method|# def current_user(*args, &block)# controller.send(:'current_user', *args, &block)# end_helpers_for_modification.class_eval<<~ruby_eval.lines.map(&:strip).join(";"),file,line
def #{method}(*args, &block)
controller.send(:'#{method}', *args, &block)
end
ruby2_keywords(:'#{method}')
ruby_evalendend# Includes the given modules in the template class.## Modules can be specified in different ways. All of the following calls# include +FooHelper+:## # Module, recommended.# helper FooHelper## # String/symbol without the "helper" suffix, camel or snake case.# helper "Foo"# helper :Foo# helper "foo"# helper :foo## The last two assume that <tt>"foo".camelize</tt> returns "Foo".## When strings or symbols are passed, the method finds the actual module# object using String#constantize. Therefore, if the module has not been# yet loaded, it has to be autoloadable, which is normally the case.## Namespaces are supported. The following calls include +Foo::BarHelper+:## # Module, recommended.# helper Foo::BarHelper## # String/symbol without the "helper" suffix, camel or snake case.# helper "Foo::Bar"# helper :"Foo::Bar"# helper "foo/bar"# helper :"foo/bar"## The last two assume that <tt>"foo/bar".camelize</tt> returns "Foo::Bar".## The method accepts a block too. If present, the block is evaluated in# the context of the controller helper module. This simple call makes the# +wadus+ method available in templates of the enclosing controller:## helper do# def wadus# "wadus"# end# end## Furthermore, all the above styles can be mixed together:## helper FooHelper, "woo", "bar/baz" do# def wadus# "wadus"# end# end#defhelper(*args,&block)modules_for_helpers(args).eachdo|mod|nextif_helpers.include?(mod)_helpers_for_modification.include(mod)end_helpers_for_modification.module_eval(&block)ifblock_given?end# Clears up all existing helpers in this class, only keeping the helper# with the same name as this class.defclear_helpersinherited_helper_methods=_helper_methodsself._helpers=Module.newself._helper_methods=Array.newinherited_helper_methods.each{|meth|helper_methodmeth}default_helper_module!unlessanonymous?end# Given an array of values like the ones accepted by +helper+, this method# returns an array with the corresponding modules, in the same order.defmodules_for_helpers(modules_or_helper_prefixes)modules_or_helper_prefixes.flatten.map!do|module_or_helper_prefix|casemodule_or_helper_prefixwhenModulemodule_or_helper_prefixwhenString,Symbolhelper_prefix=module_or_helper_prefix.to_shelper_prefix=helper_prefix.camelizeunlesshelper_prefix.start_with?(/[A-Z]/)"#{helper_prefix}Helper".constantizeelseraiseArgumentError,"helper must be a String, Symbol, or Module"endendenddef_helpers_for_modificationunless@_helpersself._helpers=define_helpers_module(self,superclass._helpers)end_helpersendprivatedefdefine_helpers_module(klass,helpers=nil)# In some tests inherited is called explicitly. In that case, just# return the module from the first time it was definedreturnklass.const_get(:HelperMethods)ifklass.const_defined?(:HelperMethods,false)mod=Module.newklass.const_set(:HelperMethods,mod)mod.include(helpers)ifhelpersmodenddefdefault_helper_module!helper_prefix=name.delete_suffix("Controller")helper(helper_prefix)rescueNameError=>eraiseunlesse.missing_name?("#{helper_prefix}Helper")endendendend