@@ -104,10 +104,12 @@ def initialize(params) # :nodoc:
104104 # params = ActionController::Parameters.new(key: 'value')
105105 # params[:key] # => "value"
106106 # params["key"] # => "value"
107- class Parameters < ActiveSupport :: HashWithIndifferentAccess
107+ class Parameters
108108 cattr_accessor :permit_all_parameters , instance_accessor : false
109109 cattr_accessor :action_on_unpermitted_parameters , instance_accessor : false
110110
111+ delegate :keys , :key? , :has_key? , :empty? , :inspect , to : :@parameters
112+
111113 # By default, never raise an UnpermittedParameters exception if these
112114 # params are present. The default includes both 'controller' and 'action'
113115 # because they are added by Rails and should be of no concern. One way
@@ -144,11 +146,19 @@ def self.const_missing(const_name)
144146 # params = ActionController::Parameters.new(name: 'Francesco')
145147 # params.permitted? # => true
146148 # Person.new(params) # => #<Person id: nil, name: "Francesco">
147- def initialize ( attributes = nil )
148- super ( attributes )
149+ def initialize ( parameters = { } )
150+ @parameters = parameters . with_indifferent_access
149151 @permitted = self . class . permit_all_parameters
150152 end
151153
154+ def ==( other_hash )
155+ if other_hash . respond_to? ( :permitted? )
156+ super
157+ else
158+ @parameters == other_hash
159+ end
160+ end
161+
152162 # Returns a safe +Hash+ representation of this parameter with all
153163 # unpermitted keys removed.
154164 #
@@ -162,28 +172,25 @@ def initialize(attributes = nil)
162172 # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
163173 def to_h
164174 if permitted?
165- to_hash
175+ @parameters . to_h
166176 else
167177 slice ( *self . class . always_permitted_parameters ) . permit! . to_h
168178 end
169179 end
170180
171181 # Returns an unsafe, unfiltered +Hash+ representation of this parameter.
172182 def to_unsafe_h
173- to_hash
183+ @parameters
174184 end
175185 alias_method :to_unsafe_hash , :to_unsafe_h
176186
177187 # Convert all hashes in values into parameters, then yield each pair like
178188 # the same way as <tt>Hash#each_pair</tt>
179189 def each_pair ( &block )
180- super do |key , value |
181- convert_hashes_to_parameters ( key , value )
190+ @parameters . each_pair do |key , value |
191+ yield key , convert_hashes_to_parameters ( key , value )
182192 end
183-
184- super
185193 end
186-
187194 alias_method :each , :each_pair
188195
189196 # Attribute that keeps track of converted arrays, if any, to avoid double
@@ -347,7 +354,11 @@ def permit(*filters)
347354 # params[:person] # => {"name"=>"Francesco"}
348355 # params[:none] # => nil
349356 def []( key )
350- convert_hashes_to_parameters ( key , super )
357+ convert_hashes_to_parameters ( key , @parameters [ key ] )
358+ end
359+
360+ def []=( key , value )
361+ @parameters [ key ] = value
351362 end
352363
353364 # Returns a parameter for the given +key+. If the +key+
@@ -361,8 +372,12 @@ def [](key)
361372 # params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
362373 # params.fetch(:none, 'Francesco') # => "Francesco"
363374 # params.fetch(:none) { 'Francesco' } # => "Francesco"
364- def fetch ( key , *args )
365- convert_hashes_to_parameters ( key , super , false )
375+ def fetch ( key , *args , &block )
376+ convert_hashes_to_parameters (
377+ key ,
378+ @parameters . fetch ( key , *args , &block ) ,
379+ false
380+ )
366381 rescue KeyError
367382 raise ActionController ::ParameterMissing . new ( key )
368383 end
@@ -375,7 +390,16 @@ def fetch(key, *args)
375390 # params.slice(:a, :b) # => {"a"=>1, "b"=>2}
376391 # params.slice(:d) # => {}
377392 def slice ( *keys )
378- new_instance_with_inherited_permitted_status ( super )
393+ new_instance_with_inherited_permitted_status ( @parameters . slice ( *keys ) )
394+ end
395+
396+ def slice! ( *keys )
397+ @parameters . slice! ( *keys )
398+ self
399+ end
400+
401+ def except ( *keys )
402+ new_instance_with_inherited_permitted_status ( @parameters . except ( *keys ) )
379403 end
380404
381405 # Removes and returns the key/value pairs matching the given keys.
@@ -384,7 +408,7 @@ def slice(*keys)
384408 # params.extract!(:a, :b) # => {"a"=>1, "b"=>2}
385409 # params # => {"c"=>3}
386410 def extract! ( *keys )
387- new_instance_with_inherited_permitted_status ( super )
411+ new_instance_with_inherited_permitted_status ( @parameters . extract! ( * keys ) )
388412 end
389413
390414 # Returns a new <tt>ActionController::Parameters</tt> with the results of
@@ -393,36 +417,70 @@ def extract!(*keys)
393417 # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
394418 # params.transform_values { |x| x * 2 }
395419 # # => {"a"=>2, "b"=>4, "c"=>6}
396- def transform_values
397- if block_given?
398- new_instance_with_inherited_permitted_status ( super )
420+ def transform_values ( &block )
421+ if block
422+ new_instance_with_inherited_permitted_status (
423+ @parameters . transform_values ( &block )
424+ )
399425 else
400- super
426+ @parameters . transform_values
401427 end
402428 end
403429
430+ def transform_values! ( &block )
431+ @parameters . transform_values! ( &block )
432+ self
433+ end
434+
404435 # This method is here only to make sure that the returned object has the
405436 # correct +permitted+ status. It should not matter since the parent of
406437 # this object is +HashWithIndifferentAccess+
407- def transform_keys # :nodoc:
408- if block_given?
409- new_instance_with_inherited_permitted_status ( super )
438+ def transform_keys ( &block ) # :nodoc:
439+ if block
440+ new_instance_with_inherited_permitted_status (
441+ @parameters . transform_keys ( &block )
442+ )
410443 else
411- super
444+ @parameters . transform_keys
412445 end
413446 end
414447
448+ def transform_keys! ( &block )
449+ @parameters . transform_keys! ( &block )
450+ self
451+ end
452+
415453 # Deletes and returns a key-value pair from +Parameters+ whose key is equal
416454 # to key. If the key is not found, returns the default value. If the
417455 # optional code block is given and the key is not found, pass in the key
418456 # and return the result of block.
419457 def delete ( key , &block )
420- convert_hashes_to_parameters ( key , super , false )
458+ convert_hashes_to_parameters ( key , @parameters . delete ( key ) , false )
459+ end
460+
461+ def select ( &block )
462+ new_instance_with_inherited_permitted_status ( @parameters . select ( &block ) )
421463 end
422464
423465 # Equivalent to Hash#keep_if, but returns nil if no changes were made.
424466 def select! ( &block )
425- convert_value_to_parameters ( super )
467+ @parameters . select! ( &block )
468+ self
469+ end
470+ alias_method :keep_if , :select!
471+
472+ def reject ( &block )
473+ new_instance_with_inherited_permitted_status ( @parameters . reject ( &block ) )
474+ end
475+
476+ def reject! ( &block )
477+ @parameters . reject! ( &block )
478+ self
479+ end
480+ alias_method :delete_if , :reject!
481+
482+ def values_at ( *keys )
483+ convert_value_to_parameters ( @parameters . values_at ( *keys ) )
426484 end
427485
428486 # Returns an exact copy of the <tt>ActionController::Parameters</tt>
@@ -439,6 +497,18 @@ def dup
439497 end
440498 end
441499
500+ def merge ( other_hash )
501+ new_instance_with_inherited_permitted_status (
502+ @parameters . merge ( other_hash )
503+ )
504+ end
505+
506+ # This is required by ActiveModel attribute assignment, so that user can
507+ # pass +Parameters+ to a mass assignment methods in a model.
508+ def stringify_keys
509+ dup
510+ end
511+
442512 protected
443513 def permitted = ( new_permitted )
444514 @permitted = new_permitted
@@ -453,7 +523,7 @@ def new_instance_with_inherited_permitted_status(hash)
453523
454524 def convert_hashes_to_parameters ( key , value , assign_if_converted = true )
455525 converted = convert_value_to_parameters ( value )
456- self [ key ] = converted if assign_if_converted && !converted . equal? ( value )
526+ @parameters [ key ] = converted if assign_if_converted && !converted . equal? ( value )
457527 converted
458528 end
459529
@@ -482,7 +552,8 @@ def each_element(object)
482552 end
483553
484554 def fields_for_style? ( object )
485- object . is_a? ( Hash ) && object . all? { |k , v | k =~ /\A -?\d +\z / && v . is_a? ( Hash ) }
555+ ( object . is_a? ( Hash ) || object . is_a? ( Parameters ) ) &&
556+ object . to_unsafe_h . all? { |k , v | k =~ /\A -?\d +\z / && v . is_a? ( Hash ) }
486557 end
487558
488559 def unpermitted_parameters! ( params )
@@ -571,7 +642,7 @@ def hash_filter(params, filter)
571642 else
572643 # Declaration { user: :name } or { user: [:name, :age, { address: ... }] }.
573644 params [ key ] = each_element ( value ) do |element |
574- if element . is_a? ( Hash )
645+ if element . is_a? ( Hash ) || element . is_a? ( Parameters )
575646 element = self . class . new ( element ) unless element . respond_to? ( :permit )
576647 element . permit ( *Array . wrap ( filter [ key ] ) )
577648 end
0 commit comments