class Praxis::Types::MultipartArray
Attributes
attributes[R]
identifier[R]
multiple[R]
options[R]
content_type[R]
preamble[RW]
Public Class Methods
construct(constructor_block, _options={})
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 44 def self.construct(constructor_block, _options={}) Class.new(self, &constructor_block) end
constructable?()
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 40 def self.constructable? true end
describe(shallow=true, example: nil)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 157 def self.describe(shallow=true, example: nil) type_name = Attributor.type_name(self) hash = { name: type_name.gsub(Attributor::MODULE_PREFIX_REGEX, ''), family: self.family, id: self.id } hash[:example] = example if example hash[:part_name] = {type: name_type.describe(true)} unless shallow hash[:attributes] = {} if self.attributes.keys.any? { |name| name.kind_of? String} hash[:pattern_attributes] = {} if self.attributes.keys.any? { |name| name.kind_of? Regexp} if hash.key?(:attributes) || hash.key?(:pattern_attributes) self.describe_attributes(shallow, example: example).each do |name, sub_hash| case name when String hash[:attributes][name] = sub_hash when Regexp hash[:pattern_attributes][name.source] = sub_hash end end else hash[:part_payload] = {type: payload_type.describe(true)} end end hash end
describe_attributes(shallow=true, example: nil)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 188 def self.describe_attributes(shallow=true, example: nil) self.attributes.each_with_object({}) do |(part_name, part_attribute), parts| sub_example = example.part(part_name) if example if sub_example && self.multiple.include?(part_name) sub_example = sub_example.first end sub_hash = part_attribute.describe(shallow, example: sub_example) if (options = sub_hash.delete(:options)) sub_hash[:options] = {} if self.multiple.include?(part_name) sub_hash[:options][:multiple] = true end if (payload_attribute = options.delete :payload_attribute) if (required = payload_attribute.options[:required]) sub_hash[:options][:required] = true end end end sub_hash[:type] = MultipartPart.describe(shallow, example: sub_example, options: part_attribute.options) parts[part_name] = sub_hash end end
dump(value, **opts)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 310 def self.dump(value, **opts) value.dump(**opts) end
example(context=Attributor::DEFAULT_ROOT_CONTEXT, **options)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 135 def self.example(context=Attributor::DEFAULT_ROOT_CONTEXT, **options) example = self.new self.attributes.each do |name, attribute| next if name.kind_of? Regexp sub_context = self.generate_subcontext(context, name) part = attribute.example(sub_context) part.name = name example.push part if self.multiple.include? name part = attribute.example(sub_context + ['2']) part.name = name example.push part end end example end
file(name, payload_type=nil, filename: nil, **opts, &block)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 112 def self.file(name, payload_type=nil, filename: nil, **opts, &block) self.part(name, payload_type, filename: true, **opts, &block) end
inherited(klass)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 14 def self.inherited(klass) klass.instance_eval do @attributes = FuzzyHash.new @saved_blocks = [] @multiple = [] @options = {} @payload_type = Attributor::String @name_type = Attributor::String @member_type = Praxis::MultipartPart @payload_attribute = nil @part_attribute = nil @identifier = MediaTypeIdentifier.load('multipart/form-data').freeze end end
load(value, context=Attributor::DEFAULT_ROOT_CONTEXT, content_type:nil)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 116 def self.load(value, context=Attributor::DEFAULT_ROOT_CONTEXT, content_type:nil) return value if value.kind_of?(self) || value.nil? if value.kind_of?(::String) && content_type.nil? raise ArgumentError, "content_type is required to load values of type String for #{Attributor.type_name(self)}" end parser = Praxis::MultipartParser.new({'Content-Type' => content_type}, value) preamble, parts = parser.parse instance = self.new instance.push(*parts) instance.preamble = preamble instance.content_type = content_type instance end
name_type(type=nil)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 48 def self.name_type(type=nil) return @name_type if type.nil? @name_type = Attributor.resolve_type type end
new(content_type: self.class.identifier)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 221 def initialize(content_type: self.class.identifier) self.content_type = content_type end
part(name, payload_type=nil, multiple: false, filename: false, **opts, &block)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 76 def self.part(name, payload_type=nil, multiple: false, filename: false, **opts, &block) @attributes.default_proc = nil if name.kind_of?(Regexp) raise 'part with regexp name may not take :multiple option' if multiple raise 'part with regexp name may not be required' if opts[:required] == true end self.multiple << name if multiple compiler = Attributor::DSLCompiler.new(self, opts) if filename filename_attribute = compiler.define('filename', String, required: true) end if block_given? definition = PartDefinition.new(&block) payload_attribute = definition.payload_attribute header_attribute = definition.headers_attribute filename_attribute = definition.filename_attribute || filename_attribute self.attributes[name] = compiler.define(name, Praxis::MultipartPart, payload_attribute: payload_attribute, headers_attribute: header_attribute, filename_attribute: filename_attribute ) else payload_attribute = compiler.define(name, payload_type || self.payload_type, **opts) self.attributes[name] = compiler.define(name, Praxis::MultipartPart, payload_attribute: payload_attribute, filename_attribute: filename_attribute ) end end
part_attribute()
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 72 def self.part_attribute @part_attribute ||= Attributor::Attribute.new(Praxis::MultipartPart, payload_attribute: self.payload_attribute) end
payload_attribute()
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 68 def self.payload_attribute @payload_attribute ||= Attributor::Attribute.new(@payload_type) end
payload_type(type=nil, **opts, &block)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 54 def self.payload_type(type=nil, **opts, &block) if type.nil? if block_given? type = Attributor::Struct else return @payload_type end end @payload_type = Attributor.resolve_type(type) @payload_attribute = Attributor::Attribute.new(@payload_type, **opts, &block) @part_attribute = nil @payload_type end
Public Instance Methods
content_type=(content_type)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 225 def content_type=(content_type) @content_type = MediaTypeIdentifier.load(content_type) if @content_type.parameters.get('boundary').nil? @content_type.parameters.set 'boundary', 'Boundary_puppies' end @content_type end
dump(**opts)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 314 def dump(**opts) boundary = content_type.parameters.get 'boundary' parts = self.collect do |part| part.dump(**opts) end all_entities = parts.join("\r\n--#{boundary}\r\n") "--#{boundary}\r\n#{all_entities}\r\n--#{boundary}--\r\n" end
part(name)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 279 def part(name) if self.class.multiple.include?(name) self.select { |i| i.name == name } else self.find { |i| i.name == name } end end
payload_type()
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 233 def payload_type self.class.payload_type end
push(*parts, context: Attributor::DEFAULT_ROOT_CONTEXT)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 237 def push(*parts, context: Attributor::DEFAULT_ROOT_CONTEXT) part, *rest = parts if rest.any? return self.push(part, context: context).push(*rest, context:context) end original_context = context part.name = self.class.name_type.load(part.name, self.class.generate_subcontext(context, part.name)) key = part.name context = self.class.generate_subcontext(context, key) # If no attributes are defined, we always use the default # payload_attribute, otherwise we constrain the parts # to the defined names. attribute = if self.class.attributes.empty? self.class.part_attribute elsif (default_thingy = self.class.attributes[key]) default_thingy else nil end if attribute part.attribute = attribute part.load_payload(context + ['payload']) part.load_headers(context + ['headers']) return self << part elsif self.class.options[:case_insensitive_load] name = self.class.attributes.keys.find do |k| k.kind_of?(String) && key.downcase == k.downcase end if name part.name = name return self.push(part, context: original_context) end end raise Attributor::AttributorException, "Unknown part name received: #{key.inspect} while loading #{Attributor.humanize_context(context)}" end
validate(context=Attributor::DEFAULT_ROOT_CONTEXT)
click to toggle source
# File lib/praxis/types/multipart_array.rb, line 287 def validate(context=Attributor::DEFAULT_ROOT_CONTEXT) errors = self.each_with_index.each_with_object([]) do |(part, idx), errors| sub_context = if part.name self.class.generate_subcontext(context, part.name) else context + ["at(#{idx})"] end errors.push *part.validate(sub_context) end self.class.attributes.each do |name, attribute| payload_attribute = attribute.options[:payload_attribute] next unless payload_attribute.options[:required] next if self.part(name) sub_context = self.class.generate_subcontext(context, name) errors.push *payload_attribute.validate_missing_value(sub_context) end errors end