@@ -28,36 +28,38 @@ def self.post_filter_methods(type)
2828 # Methods which should not be available in filters until the before filter
2929 # has completed
3030 module PostBeforeFilter
31- def declared ( passed_params , options = { } , declared_params = nil )
31+ def declared ( passed_params , options = { } , declared_params = nil , params_nested_path = [ ] )
3232 options = options . reverse_merge ( include_missing : true , include_parent_namespaces : true )
3333 declared_params ||= optioned_declared_params ( **options )
3434
3535 if passed_params . is_a? ( Array )
36- declared_array ( passed_params , options , declared_params )
36+ declared_array ( passed_params , options , declared_params , params_nested_path )
3737 else
38- declared_hash ( passed_params , options , declared_params )
38+ declared_hash ( passed_params , options , declared_params , params_nested_path )
3939 end
4040 end
4141
4242 private
4343
44- def declared_array ( passed_params , options , declared_params )
44+ def declared_array ( passed_params , options , declared_params , params_nested_path )
4545 passed_params . map do |passed_param |
46- declared ( passed_param || { } , options , declared_params )
46+ declared ( passed_param || { } , options , declared_params , params_nested_path )
4747 end
4848 end
4949
50- def declared_hash ( passed_params , options , declared_params )
50+ def declared_hash ( passed_params , options , declared_params , params_nested_path )
5151 declared_params . each_with_object ( passed_params . class . new ) do |declared_param , memo |
5252 if declared_param . is_a? ( Hash )
5353 declared_param . each_pair do |declared_parent_param , declared_children_params |
54+ params_nested_path_dup = params_nested_path . dup
55+ params_nested_path_dup << declared_parent_param . to_s
5456 next unless options [ :include_missing ] || passed_params . key? ( declared_parent_param )
5557
5658 passed_children_params = passed_params [ declared_parent_param ] || passed_params . class . new
5759 memo_key = optioned_param_key ( declared_parent_param , options )
5860
59- memo [ memo_key ] = handle_passed_param ( declared_parent_param , passed_children_params ) do
60- declared ( passed_children_params , options , declared_children_params )
61+ memo [ memo_key ] = handle_passed_param ( passed_children_params , params_nested_path_dup ) do
62+ declared ( passed_children_params , options , declared_children_params , params_nested_path_dup )
6163 end
6264 end
6365 else
@@ -77,19 +79,34 @@ def declared_hash(passed_params, options, declared_params)
7779 end
7880 end
7981
80- def handle_passed_param ( declared_param , passed_children_params , &_block )
81- should_be_empty_array? ( declared_param , passed_children_params ) ? [ ] : yield
82+ def handle_passed_param ( passed_children_params , params_nested_path , &_block )
83+ if should_be_empty_hash? ( passed_children_params , params_nested_path )
84+ { }
85+ elsif should_be_empty_array? ( passed_children_params , params_nested_path )
86+ [ ]
87+ else
88+ yield
89+ end
8290 end
8391
84- def should_be_empty_array? ( declared_param , passed_children_params )
85- declared_param_is_array? ( declared_param ) && passed_children_params . empty?
92+ def should_be_empty_array? ( passed_children_params , params_nested_path )
93+ passed_children_params . empty? && declared_param_is_array? ( params_nested_path )
8694 end
8795
88- def declared_param_is_array? ( declared_param )
89- key = declared_param . to_s
96+ def declared_param_is_array? ( params_nested_path )
97+ key = route_options_params_key ( params_nested_path )
9098 route_options_params [ key ] && route_options_params [ key ] [ :type ] == 'Array'
9199 end
92100
101+ def should_be_empty_hash? ( passed_children_params , params_nested_path )
102+ passed_children_params . empty? && declared_param_is_hash? ( params_nested_path )
103+ end
104+
105+ def declared_param_is_hash? ( params_nested_path )
106+ key = route_options_params_key ( params_nested_path )
107+ route_options_params [ key ] && route_options_params [ key ] [ :type ] == 'Hash'
108+ end
109+
93110 def route_options_params
94111 options [ :route_options ] [ :params ] || { }
95112 end
@@ -98,6 +115,12 @@ def optioned_param_key(declared_param, options)
98115 options [ :stringify ] ? declared_param . to_s : declared_param . to_sym
99116 end
100117
118+ def route_options_params_key ( params_nested_path )
119+ key = params_nested_path [ 0 ]
120+ key += '[' + params_nested_path [ 1 ..-1 ] . join ( '][' ) + ']' if params_nested_path . size > 1
121+ key
122+ end
123+
101124 def optioned_declared_params ( **options )
102125 declared_params = if options [ :include_parent_namespaces ]
103126 # Declared params including parent namespaces
0 commit comments