module IknowParams::Parser
IknowParams::Parser
provides a mix-in for ActiveRecord controllers to parse input parameters.
Constants
- BLANK
- PARAM_REQUIRED
Public Class Methods
# File lib/iknow_params/parser.rb, line 27 def parse_hash(hash, &block) HashParser.new(hash).parse(&block) end
# File lib/iknow_params/parser.rb, line 31 def parse_value(value, **args) HashParser.new({ sentinel: value }).parse_param(:sentinel, **args) end
# File lib/iknow_params/parser.rb, line 35 def parse_values(values, **args) HashParser.new({ sentinel: values }).parse_array_param(:sentinel, **args) end
Allow serializers to register themselves
# File lib/iknow_params/parser.rb, line 146 def self.register_serializer(name, serializer) define_method(:"parse_#{name.underscore}_param") do |param, default: PARAM_REQUIRED| parse_param(param, with: serializer, default: default) end define_method(:"parse_#{name.underscore}_array_param") do |param, default: PARAM_REQUIRED| parse_array_param(param, with: serializer, default: default) end end
Public Instance Methods
Parse an array-typed param using the provided serializer for each member element.
# File lib/iknow_params/parser.rb, line 89 def parse_array_param(param, with: nil, default: PARAM_REQUIRED, dump: false) serializer = case with when String, Symbol IknowParams::Serializer.for!(with) else with end vals = params[param] parses = if vals.nil? raise ParseError.new("Required parameter '#{param}' missing", param, nil) if default == PARAM_REQUIRED default elsif !vals.is_a?(Array) raise ParseError.new("Invalid type for parameter '#{param}': '#{vals.class.name}'", param, vals) elsif serializer.present? vals.map do |val| begin serializer.load(val) rescue IknowParams::Serializer::LoadError => ex raise ParseError.new("Invalid member in array parameter '#{param}': '#{val.inspect}' - #{ex.message}", param, val) end end else vals end if dump && parses != BLANK parses.map! { |v| serializer.dump(v) } end parses end
Parse the specified parameter, optionally deserializing with the provided IKnowParams::Serializer. If the parameter is missing and no default is provided, raises a ParseError
.
If `BLANK` is provided as a default, return a placeholder object that can be later stripped out with `remove_blanks`
If `dump` is true, use the serializer to re-serialize any successfully parsed argument back to a canonical string. This can be useful to validate and normalize the input to another service without parsing it. A serializer must be passed to use this option.
# File lib/iknow_params/parser.rb, line 51 def parse_param(param, with: nil, default: PARAM_REQUIRED, dump: false) serializer = case with when String, Symbol IknowParams::Serializer.for!(with) else with end parse = if !params.has_key?(param) raise ParseError.new("Required parameter '#{param}' missing", param, nil) if default == PARAM_REQUIRED default else val = params[param] if serializer.present? begin serializer.load(val) rescue IknowParams::Serializer::LoadError => ex raise ParseError.new("Invalid parameter '#{param}': '#{val.inspect}' - #{ex.message}", param, val) end else val end end if dump && parse != BLANK begin parse = serializer.dump(parse) rescue NoMethodError => ex raise ParseError.new("Serializer '#{serializer}' can't dump param '#{param}' #{val.inspect} - #{ex.message}", param, val) end end parse end
Convenience method to make it simpler to build a hash structure with optional members from parsed data. This method recursively traverses the provided structure and removes any instances of the sentinel value Parser::BLANK.
# File lib/iknow_params/parser.rb, line 129 def remove_blanks(arg) case arg when Hash arg.each do |k, v| if v == BLANK arg.delete(k) else remove_blanks(v) end end when Array arg.delete(BLANK) arg.each { |e| remove_blanks(e) } end end