module ApiRegulator module ControllerMixin def validate_params! validator_class = Validator.get(params[:controller], params[:action]) unless validator_class raise "No validator found for HTTP method #{request.method} and API path #{api_definition.path}" end validator = validator_class.new(api_params) unless validator.valid? raise ApiRegulator::ValidationError.new(validator.errors) end end def api_definition return @api_definition if defined?(@api_definition) @api_definition ||= self.class.api_definitions.find do |d| d.controller_path == params[:controller] && d.action_name == params[:action] end raise "API definition not found for #{params[:controller]}##{params[:action]}" unless @api_definition @api_definition end def api_params path_params = api_definition.params.select(&:path?).each_with_object({}) do |param, hash| hash[param.name.to_sym] = params[param.name] if params.key?(param.name) end.symbolize_keys query_params = api_definition.params.select(&:query?).each_with_object({}) do |param, hash| hash[param.name.to_sym] = params[param.name] if params.key?(param.name) end.symbolize_keys body_params = api_definition.params.select(&:body?) permitted_body = body_params.each_with_object({}) do |param, hash| if param.type == :object if param.required? nested = params.expect(param.name => build_permitted_keys(param.children)).to_h.symbolize_keys hash[param.name.to_sym] = nested else nested = params.permit(param.name => build_permitted_keys(param.children)).to_h.symbolize_keys hash.merge!(nested) end else hash[param.name.to_sym] = params[param.name] end end.symbolize_keys path_params.merge(query_params).merge(permitted_body).symbolize_keys end private def build_permitted_keys(params) params.map do |param| if param.children.any? { param.name.to_sym => build_permitted_keys(param.children) } else param.name.to_sym end end end end end