|
9 | 9 | module Rapid
|
10 | 10 | class ArgumentSet
|
11 | 11 |
|
| 12 | + # This is a constant that represents a missing value where `nil` means |
| 13 | + # the user actually wanted to send null/nil. |
| 14 | + class MissingValue |
| 15 | + |
| 16 | + def self.singleton |
| 17 | + @singleton ||= new |
| 18 | + end |
| 19 | + |
| 20 | + end |
| 21 | + |
12 | 22 | extend Defineable
|
13 | 23 |
|
14 | 24 | class << self
|
@@ -57,12 +67,13 @@ def initialize(hash, path: [], request: nil)
|
57 | 67 | @source = self.class.definition.arguments.each_with_object({}) do |(arg_key, argument), source|
|
58 | 68 | given_value = lookup_value(hash, arg_key, argument, request)
|
59 | 69 |
|
60 |
| - next if given_value.nil? && !argument.required? |
61 |
| - |
62 |
| - if given_value.nil? |
| 70 | + if argument.required? && (given_value.nil? || given_value.is_a?(MissingValue)) |
63 | 71 | raise MissingArgumentError.new(argument, path: @path + [argument])
|
64 | 72 | end
|
65 | 73 |
|
| 74 | + # If the given value is missing, we'll just skip adding this to the hash |
| 75 | + next if given_value.is_a?(MissingValue) |
| 76 | + |
66 | 77 | given_value = parse_value(argument, given_value)
|
67 | 78 | validation_errors = argument.validate_value(given_value)
|
68 | 79 | unless validation_errors.empty?
|
@@ -112,12 +123,19 @@ def lookup_value(hash, key, argument, request)
|
112 | 123 | elsif hash.key?(key.to_sym)
|
113 | 124 | hash[key.to_sym]
|
114 | 125 | else
|
115 |
| - value_from_route(argument, request) || argument.default |
| 126 | + route_value = value_from_route(argument, request) |
| 127 | + return route_value unless route_value.is_a?(MissingValue) |
| 128 | + return argument.default unless argument.default.nil? |
| 129 | + |
| 130 | + MissingValue.singleton |
116 | 131 | end
|
117 | 132 | end
|
118 | 133 |
|
119 | 134 | def parse_value(argument, value, index: nil, in_array: false)
|
120 |
| - if argument.array? && value.is_a?(Array) |
| 135 | + if value.nil? |
| 136 | + nil |
| 137 | + |
| 138 | + elsif argument.array? && value.is_a?(Array) |
121 | 139 | value.each_with_index.map do |v, i|
|
122 | 140 | parse_value(argument, v, index: i, in_array: true)
|
123 | 141 | end
|
@@ -167,12 +185,15 @@ def check_for_missing_required_arguments
|
167 | 185 | end
|
168 | 186 |
|
169 | 187 | def value_from_route(argument, request)
|
170 |
| - return if request.nil? |
171 |
| - return if request.route.nil? |
| 188 | + return MissingValue.singleton if request.nil? |
| 189 | + return MissingValue.singleton if request.route.nil? |
172 | 190 |
|
173 | 191 | route_args = request.route.extract_arguments(request.api_path)
|
174 |
| - value_for_arg = route_args[argument.name.to_s] |
| 192 | + unless route_args.key?(argument.name.to_s) |
| 193 | + return MissingValue.singleton |
| 194 | + end |
175 | 195 |
|
| 196 | + value_for_arg = route_args[argument.name.to_s] |
176 | 197 | return nil if value_for_arg.nil?
|
177 | 198 |
|
178 | 199 | if argument.type.argument_set?
|
|
0 commit comments