Class: ActionDispatch::ParamBuilder
Relationships & Source Files | |
Inherits: | Object |
Defined in: | actionpack/lib/action_dispatch/http/param_builder.rb |
Constant Summary
-
LEADING_BRACKETS_COMPAT =
# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 21defined?(::Rack::RELEASE) && ::Rack::RELEASE.to_s.start_with?("2.")
Class Attribute Summary
- .default (also: #default) rw
- .ignore_leading_brackets (also: #ignore_leading_brackets) rw
Class Method Summary
Instance Attribute Summary
Instance Method Summary
Constructor Details
.new(param_depth_limit) ⇒ ParamBuilder
# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 15
def initialize(param_depth_limit) @param_depth_limit = param_depth_limit end
Class Attribute Details
.default (rw) Also known as: #default
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 23
cattr_accessor :default
.ignore_leading_brackets (rw) Also known as: #ignore_leading_brackets
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 19
cattr_accessor :ignore_leading_brackets
Class Method Details
.make_default(param_depth_limit)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 9
def self.make_default(param_depth_limit) new param_depth_limit end
Instance Attribute Details
#default (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 23
cattr_accessor :default
#from_hash(hash, encoding_template: nil) (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 50
delegate :from_query_string, :from_pairs, :from_hash, to: :default
#from_pairs(pairs, encoding_template: nil) (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 34
delegate :from_query_string, :from_pairs, :from_hash, to: :default
#from_query_string(qs, separator: nil, encoding_template: nil) (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 30
delegate :from_query_string, :from_pairs, :from_hash, to: :default
#ignore_leading_brackets (rw)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 19
cattr_accessor :ignore_leading_brackets
#param_depth_limit (readonly)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 13
attr_reader :param_depth_limit
Instance Method Details
#make_params (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 162
def make_params ActiveSupport::HashWithIndifferentAccess.new end
#new_depth_limit(param_depth_limit) (private)
[ GitHub ]# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 166
def new_depth_limit(param_depth_limit) self.class.new @params_class, param_depth_limit end
#params_hash_has_key?(hash, key) ⇒ Boolean
(private)
# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 174
def params_hash_has_key?(hash, key) return false if key.include?("[]") key.split(/[\[\]]+/).inject(hash) do |h, part| next h if part == "" return false unless params_hash_type?(h) && h.key?(part) h[part] end true end
#params_hash_type?(obj) ⇒ Boolean
(private)
# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 170
def params_hash_type?(obj) Hash === obj end
#store_nested_param(params, name, v, depth, encoding_template = nil) (private)
# File 'actionpack/lib/action_dispatch/http/param_builder.rb', line 65
def store_nested_param(params, name, v, depth, encoding_template = nil) raise ParamsTooDeepError if depth >= param_depth_limit if !name # nil name, treat same as empty string (required by tests) k = after = "" elsif depth == 0 if ignore_leading_brackets || (ignore_leading_brackets.nil? && LEADING_BRACKETS_COMPAT) # Rack 2 compatible behavior, ignore leading brackets if name =~ /\A[\[\]]*([^\[\]]+)\]*/ k = $1 after = $' || "" if !ignore_leading_brackets && (k != $& || !after.empty? && !after.start_with?("[")) ActionDispatch.deprecator.warn("Skipping over leading brackets in parameter name #{name.inspect} is deprecated and will parse differently in Rails 8.1 or Rack 3.0.") end else k = name after = "" end else # Start of parsing, don't treat [] or [ at start of string specially if start = name.index("[", 1) # Start of parameter nesting, use part before brackets as key k = name[0, start] after = name[start, name.length] else # Plain parameter with no nesting k = name after = "" end end elsif name.start_with?("[]") # Array nesting k = "[]" after = name[2, name.length] elsif name.start_with?("[") && (start = name.index("]", 1)) # Hash nesting, use the part inside brackets as the key k = name[1, start - 1] after = name[start + 1, name.length] else # Probably malformed input, nested but not starting with [ # treat full name as key for backwards compatibility. k = name after = "" end return if k.empty? if depth == 0 && String === v # We have to wait until we've found the top part of the name, # because that's what the encoding template is configured with if encoding_template && (designated_encoding = encoding_template[k]) && !v.frozen? v.force_encoding(designated_encoding) end # ... and we can't validate the encoding until after we've # applied any template override unless v.valid_encoding? raise InvalidParameterError, "Invalid encoding for parameter: #{v.scrub}" end end if after == "" if k == "[]" && depth != 0 return (v || !ActionDispatch::Request::Utils.perform_deep_munge) ? [v] : [] else params[k] = v end elsif after == "[" params[name] = v elsif after == "[]" params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) params[k] << v if v || !ActionDispatch::Request::Utils.perform_deep_munge elsif after.start_with?("[]") # Recognize x[][y] (hash inside array) parameters unless after[2] == "[" && after.end_with?("]") && (child_key = after[3, after.length - 4]) && !child_key.empty? && !child_key.index("[") && !child_key.index("]") # Handle other nested array parameters child_key = after[2, after.length] end params[k] ||= [] raise ParameterTypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) if params_hash_type?(params[k].last) && !params_hash_has_key?(params[k].last, child_key) store_nested_param(params[k].last, child_key, v, depth + 1) else params[k] << store_nested_param(make_params, child_key, v, depth + 1) end else params[k] ||= make_params raise ParameterTypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params_hash_type?(params[k]) params[k] = store_nested_param(params[k], after, v, depth + 1) end params end