From 88cf2fca0c29f6ef5a335e57df527fea661e02ac Mon Sep 17 00:00:00 2001 From: Piero Dotti Date: Sun, 17 Dec 2023 23:09:50 +0100 Subject: [PATCH] fix(required): broken with nested data --- lib/paramoid/object.rb | 18 +++++++++++------- spec/paramoid/complex_spec.rb | 29 ++++++++++++++++++++++++++++- spec/paramoid/object_spec.rb | 18 +++++++++++------- spec/support/params.rb | 2 +- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/lib/paramoid/object.rb b/lib/paramoid/object.rb index 30f8631..8b00bfc 100644 --- a/lib/paramoid/object.rb +++ b/lib/paramoid/object.rb @@ -66,6 +66,13 @@ def to_required_params # @param [Array] path # @raise [ActionController::ParameterMissing] if one of the required params is missing def ensure_required_params!(params, path: []) + if params.is_a?(Array) + params.flatten.each do |param| + ensure_required_params!(param, path: path) + end + return params + end + current_path = [*path, @name] _raise_on_missing_parameter!(params, output_key, current_path) if @required @@ -76,13 +83,9 @@ def ensure_required_params!(params, path: []) end def ensure_required_nested_params!(params, current_path) - if params.is_a?(Array) - params.flatten.each do |param| - @nested.ensure_required_params!(param[output_key], path: current_path) - end - else - @nested.ensure_required_params!(params ? params[output_key] : nil, path: current_path) - end + return params if current_path.size > 1 && params.nil? + + @nested.ensure_required_params!(params ? params[output_key] : nil, path: current_path) params end @@ -156,6 +159,7 @@ def nested? private def _raise_on_missing_parameter!(params, key, current_path) + return if params.nil? return if _param_exist?(params, key) raise ActionController::ParameterMissing, current_path.join('.') diff --git a/spec/paramoid/complex_spec.rb b/spec/paramoid/complex_spec.rb index b714a0d..5a7c11a 100644 --- a/spec/paramoid/complex_spec.rb +++ b/spec/paramoid/complex_spec.rb @@ -72,6 +72,30 @@ } ) end + + context 'and the required parameter is missing' do + let(:params_hash) do + { + + unwanted: 1, + name: 'some_name', + buyer: { + payment_method: { + id: 1 + } + }, + person: {}, + items: [{}, { sub_items: [{ price: 5 }] }] + } + end + + it 'raises an error' do + expect { sanitized }.to raise_error( + ActionController::ParameterMissing, + 'param is missing or the value is empty: items.sub_items.id' + ) + end + end end end @@ -126,7 +150,10 @@ let(:user) { double(admin?: false) } let(:params_hash) do { - name: 'some_name' + name: 'some_name', + buyer: { + payment_method: {} + } } end diff --git a/spec/paramoid/object_spec.rb b/spec/paramoid/object_spec.rb index 0fa65bc..7e3b17f 100644 --- a/spec/paramoid/object_spec.rb +++ b/spec/paramoid/object_spec.rb @@ -105,11 +105,15 @@ context 'when it\'s nested' do let(:nested) { described_class.new(:nested, nil, required: true) } - it 'raises an error' do - expect do - subject.ensure_required_params!(params) - end.to raise_error(ActionController::ParameterMissing, - 'param is missing or the value is empty: some_param.nested') + context 'and some_param is present, but nested is required' do + let(:params_hash) { { 'not_this_param' => 'some_value', 'some_param' => {} } } + + it 'raises an error' do + expect do + subject.ensure_required_params!(params) + end.to raise_error(ActionController::ParameterMissing, + 'param is missing or the value is empty: some_param.nested') + end end context 'and some_param is required' do @@ -129,8 +133,8 @@ it 'skips the check' do expect do subject.ensure_required_params!(params) - end.to raise_error(ActionController::ParameterMissing, - 'param is missing or the value is empty: some_param.nested') + end.not_to raise_error(ActionController::ParameterMissing, + 'param is missing or the value is empty: some_param.nested') end end end diff --git a/spec/support/params.rb b/spec/support/params.rb index d089967..3bb9c82 100644 --- a/spec/support/params.rb +++ b/spec/support/params.rb @@ -47,7 +47,7 @@ def initialize(user = nil) param :discount, transformer: ->(data) { data&.to_f / 100 } if user.admin? array :sub_items do - param :id + param :id, required: true default :price, 0 end end