aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_controller/base.rb1
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb160
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb2
-rw-r--r--actionpack/test/controller/params_wrapper_test.rb2
-rw-r--r--actionpack/test/template/template_test.rb1
5 files changed, 106 insertions, 60 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 9b3bf99fc3..971c4189c8 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1,4 +1,5 @@
require "action_controller/log_subscriber"
+require "action_controller/metal/params_wrapper"
module ActionController
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 09abc999c1..a475d4bdff 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -1,6 +1,7 @@
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/module/anonymous'
+require 'active_support/core_ext/struct'
require 'action_dispatch/http/mime_types'
module ActionController
@@ -72,12 +73,99 @@ module ActionController
EXCLUDE_PARAMETERS = %w(authenticity_token _method utf8)
+ require 'mutex_m'
+
+ class Options < Struct.new(:name, :format, :include, :exclude, :klass, :model) # :nodoc:
+ include Mutex_m
+
+ def self.from_hash(hash)
+ name = hash[:name]
+ format = Array(hash[:format])
+ include = hash[:include] && Array(hash[:include]).collect(&:to_s)
+ exclude = hash[:exclude] && Array(hash[:exclude]).collect(&:to_s)
+ new name, format, include, exclude, nil, nil
+ end
+
+ def initialize(name, format, include, exclude, klass, model) # nodoc
+ super
+ @include_set = include
+ @name_set = name
+ end
+
+ def model
+ super || synchronize { super || self.model = _default_wrap_model }
+ end
+
+ def include
+ return super if @include_set
+
+ m = model
+ synchronize do
+ return super if @include_set
+
+ @include_set = true
+
+ unless super || exclude
+ if m.respond_to?(:attribute_names) && m.attribute_names.any?
+ self.include = m.attribute_names
+ end
+ end
+ end
+ end
+
+ def name
+ return super if @name_set
+
+ m = model
+ synchronize do
+ return super if @name_set
+
+ @name_set = true
+
+ unless super || klass.anonymous?
+ self.name = m ? m.to_s.demodulize.underscore :
+ klass.controller_name.singularize
+ end
+ end
+ end
+
+ private
+ # Determine the wrapper model from the controller's name. By convention,
+ # this could be done by trying to find the defined model that has the
+ # same singularize name as the controller. For example, +UsersController+
+ # will try to find if the +User+ model exists.
+ #
+ # This method also does namespace lookup. Foo::Bar::UsersController will
+ # try to find Foo::Bar::User, Foo::User and finally User.
+ def _default_wrap_model #:nodoc:
+ return nil if klass.anonymous?
+ model_name = klass.name.sub(/Controller$/, '').classify
+
+ begin
+ if model_klass = model_name.safe_constantize
+ model_klass
+ else
+ namespaces = model_name.split("::")
+ namespaces.delete_at(-2)
+ break if namespaces.last == model_name
+ model_name = namespaces.join("::")
+ end
+ end until model_klass
+
+ model_klass
+ end
+ end
+
included do
class_attribute :_wrapper_options
- self._wrapper_options = { :format => [] }
+ self._wrapper_options = Options.from_hash(format: [])
end
module ClassMethods
+ def _set_wrapper_options(options)
+ self._wrapper_options = Options.from_hash(options)
+ end
+
# Sets the name of the wrapper key, or the model which +ParamsWrapper+
# would use to determine the attribute names from.
#
@@ -119,68 +207,24 @@ module ActionController
model = name_or_model_or_options
end
- _set_wrapper_defaults(_wrapper_options.slice(:format).merge(options), model)
+ opts = Options.from_hash _wrapper_options.to_h.slice(:format).merge(options)
+ opts.model = model
+ opts.klass = self
+
+ self._wrapper_options = opts
end
# Sets the default wrapper key or model which will be used to determine
# wrapper key and attribute names. Will be called automatically when the
# module is inherited.
def inherited(klass)
- if klass._wrapper_options[:format].present?
- klass._set_wrapper_defaults(klass._wrapper_options.slice(:format))
+ if klass._wrapper_options.format.any?
+ params = klass._wrapper_options.dup
+ params.klass = klass
+ klass._wrapper_options = params
end
super
end
-
- protected
-
- # Determine the wrapper model from the controller's name. By convention,
- # this could be done by trying to find the defined model that has the
- # same singularize name as the controller. For example, +UsersController+
- # will try to find if the +User+ model exists.
- #
- # This method also does namespace lookup. Foo::Bar::UsersController will
- # try to find Foo::Bar::User, Foo::User and finally User.
- def _default_wrap_model #:nodoc:
- return nil if self.anonymous?
- model_name = self.name.sub(/Controller$/, '').classify
-
- begin
- if model_klass = model_name.safe_constantize
- model_klass
- else
- namespaces = model_name.split("::")
- namespaces.delete_at(-2)
- break if namespaces.last == model_name
- model_name = namespaces.join("::")
- end
- end until model_klass
-
- model_klass
- end
-
- def _set_wrapper_defaults(options, model=nil)
- options = options.dup
-
- unless options[:include] || options[:exclude]
- model ||= _default_wrap_model
- if model.respond_to?(:attribute_names) && model.attribute_names.present?
- options[:include] = model.attribute_names
- end
- end
-
- unless options[:name] || self.anonymous?
- model ||= _default_wrap_model
- options[:name] = model ? model.to_s.demodulize.underscore :
- controller_name.singularize
- end
-
- options[:include] = Array(options[:include]).collect(&:to_s) if options[:include]
- options[:exclude] = Array(options[:exclude]).collect(&:to_s) if options[:exclude]
- options[:format] = Array(options[:format])
-
- self._wrapper_options = options
- end
end
# Performs parameters wrapping upon the request. Will be called automatically
@@ -205,20 +249,20 @@ module ActionController
# Returns the wrapper key which will use to stored wrapped parameters.
def _wrapper_key
- _wrapper_options[:name]
+ _wrapper_options.name
end
# Returns the list of enabled formats.
def _wrapper_formats
- _wrapper_options[:format]
+ _wrapper_options.format
end
# Returns the list of parameters which will be selected for wrapped.
def _wrap_parameters(parameters)
- value = if include_only = _wrapper_options[:include]
+ value = if include_only = _wrapper_options.include
parameters.slice(*include_only)
else
- exclude = _wrapper_options[:exclude] || []
+ exclude = _wrapper_options.exclude || []
parameters.except(*(exclude + EXCLUDE_PARAMETERS))
end
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 7f42d6e9c3..e298751062 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -52,7 +52,7 @@ module ActionView
# <%= form_tag('/posts') do -%>
# <div><%= submit_tag 'Save' %></div>
# <% end -%>
- # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form>
+ # # => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form>
#
# <%= form_tag('/posts', remote: true) %>
# # => <form action="/posts" method="post" data-remote="true">
diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb
index 209f021cf7..d87e2b85b0 100644
--- a/actionpack/test/controller/params_wrapper_test.rb
+++ b/actionpack/test/controller/params_wrapper_test.rb
@@ -4,7 +4,7 @@ module Admin; class User; end; end
module ParamsWrapperTestHelp
def with_default_wrapper_options(&block)
- @controller.class._wrapper_options = {:format => [:json]}
+ @controller.class._set_wrapper_options({:format => [:json]})
@controller.class.inherited(@controller.class)
yield
end
diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb
index 86ba5f3b4d..ffee3f81ba 100644
--- a/actionpack/test/template/template_test.rb
+++ b/actionpack/test/template/template_test.rb
@@ -1,3 +1,4 @@
+# encoding: US-ASCII
require "abstract_unit"
require "logger"