# author: Vadim Shaveiko <@vshaveyko> # frozen_string_literal: true module RailsApiDoc::Controller::StrongParams ParamIsRequired = Class.new(StandardError) def resource_params # accepted_params for permit params.permit(params_to_permit) end private def params_to_permit accepted_params = [{}] loop_params(params, permitted_params, accepted_params) accepted_params end # loop through current level of params and add to permit level if all requirements are met # # requirements are: 1) if required is set - param must be present and not empty => or error is raised # 2) if enum is set - param must equal predefined value => see Config::ValidateEnum # 3) if ary_object => see Config::ValidateAryObject # 3) if config.check_params_type is set - param must be of required type # # @accepted_params = [{}] - array with last member hash for nesting # @level_params - current nesting level params # @level_permitted_params - data for params permission def loop_params(params, level_permitted_params, accepted_params) level_permitted_params.each do |param_name, api_param_data| controller_param = params[param_name] check_required(param_name, controller_param, api_param_data) # # no value present && not required => go next next unless controller_param next unless RailsApiDoc::Config::Validator.valid_param?(controller_param, api_param_data) # if settings is array if api_param_data.ary_object? controller_param.each do |single_controller_param| _next_nesting_level(single_controller_param, param_data: api_param_data, current_accepted_params: accepted_params, param_name: param_name) end elsif api_param_data.nested? _next_nesting_level(controller_param, param_data: api_param_data, current_accepted_params: accepted_params, param_name: param_name) else accepted_params.unshift(param_name) end end end def _next_nesting_level(controller_param, param_data:, current_accepted_params:, param_name:) level_accepted_params = current_accepted_params.last[param_name] = [{}] loop_params(controller_param, param_data.nesting, level_accepted_params) end def permitted_params ::RailsApiDoc::Controller::Parameter::Repository[self.class] end def check_required(param_name, param_data, param_config) return unless param_config.required? && param_data.blank? raise RailsApiDoc::Exception::ParamRequired, param_name end end