Class: Protocol::Content::Parameters::Model
- Inherits:
-
Object
- Object
- Protocol::Content::Parameters::Model
- Defined in:
- lib/protocol/content/parameters/model.rb
Overview
An immutable model for parsing, filtering, and validating parameters.
Instance Attribute Summary collapse
-
#fields ⇒ Object
readonly
The fields in this model, indexed by name.
Instance Method Summary collapse
-
#accepts_upload?(path) ⇒ Boolean
Whether an upload path is explicitly accepted by this model.
-
#apply(value, errors, path = []) ⇒ Object
Apply this model to an existing argument hierarchy.
-
#freeze ⇒ Object
Freeze this model and its fields.
-
#initialize(parser, fields, strict: true) ⇒ Model
constructor
Initialize a parameter model.
-
#parse(media_type, input, &upload_handler) ⇒ Object
Parse, filter, and validate content parameters.
-
#parse!(media_type, input, &block) ⇒ Object
Parse content parameters, raising when validation fails.
-
#upload_field(path) ⇒ Object
Find the upload field which accepts the given decoded path.
Constructor Details
#initialize(parser, fields, strict: true) ⇒ Model
Initialize a parameter model.
18 19 20 21 22 |
# File 'lib/protocol/content/parameters/model.rb', line 18 def initialize(parser, fields, strict: true) @parser = parser @fields = fields @strict = strict end |
Instance Attribute Details
#fields ⇒ Object (readonly)
The fields in this model, indexed by name.
25 26 27 |
# File 'lib/protocol/content/parameters/model.rb', line 25 def fields @fields end |
Instance Method Details
#accepts_upload?(path) ⇒ Boolean
Whether an upload path is explicitly accepted by this model.
119 120 121 |
# File 'lib/protocol/content/parameters/model.rb', line 119 def accepts_upload?(path) return !!upload_field(path) end |
#apply(value, errors, path = []) ⇒ Object
Apply this model to an existing argument hierarchy.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/protocol/content/parameters/model.rb', line 76 def apply(value, errors, path = []) # Parameter models always apply to a key/value hierarchy: unless value.is_a?(Hash) errors << Error.new(path, :invalid_type, expected: Hash, value: value) return {} end # Copy the input so declared fields can be removed without modifying caller-owned data: input = value.dup output = {} # Apply declared values and collect missing required parameters: @fields.each do |name, field| item_path = path + [name] if input.key?(name) item = input.delete(name) if item.equal?(Value::OMITTED) if field.required? errors << Error.new(item_path, :required) end else field.apply(item, output, errors, item_path) end elsif field.required? errors << Error.new(item_path, :required) end end # Reject remaining undeclared values when strict validation is enabled: if @strict input.each_key do |name| errors << Error.new(path + [name], :unknown) end end return output end |
#freeze ⇒ Object
Freeze this model and its fields.
139 140 141 142 143 144 145 146 |
# File 'lib/protocol/content/parameters/model.rb', line 139 def freeze return self if self.frozen? @parser.freeze @fields.each_value(&:freeze) @fields.freeze super end |
#parse(media_type, input, &upload_handler) ⇒ Object
Parse, filter, and validate content parameters.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/protocol/content/parameters/model.rb', line 32 def parse(media_type, input, &upload_handler) # Replace ephemeral multipart uploads with outcomes which can survive until validation: value = @parser.parse(media_type, input) do |name, item| if item.is_a?(Protocol::Multipart::FormData::Upload) path = Protocol::URL::Encoding.split(name) # Only process uploads accepted by an explicit field: if upload_handler && field = upload_field(path) field.process(name, item, &upload_handler) else Value::OMITTED end else item end end # Apply the model after parsing so ordinary values and upload outcomes follow the same hierarchy: errors = [] value = apply(value, errors) return Result.new(value, errors) end |
#parse!(media_type, input, &block) ⇒ Object
Parse content parameters, raising when validation fails.
61 62 63 64 65 66 67 68 69 |
# File 'lib/protocol/content/parameters/model.rb', line 61 def parse!(media_type, input, &block) result = parse(media_type, input, &block) if result.valid? return result.value end raise ValidationError, result end |
#upload_field(path) ⇒ Object
Find the upload field which accepts the given decoded path.
126 127 128 129 130 131 132 133 134 135 |
# File 'lib/protocol/content/parameters/model.rb', line 126 def upload_field(path) # Walk fields using the decoded components of the form name: name, *remaining = path unless field = @fields[name] return nil end return field.upload_field(remaining) end |