class Attributor::Collection

Attributes

options[R]

Public Class Methods

as_json_schema( shallow: false, example: nil, attribute_options: {} ) click to toggle source
Calls superclass method
# File lib/attributor/types/collection.rb, line 120
def self.as_json_schema( shallow: false, example: nil, attribute_options: {} )
  hash = super
  opts = self.options.merge( attribute_options )
  hash[:description] = opts[:description] if opts[:description]
  if the_default = opts[:default]
    the_object = the_default.is_a?(Proc) ? the_default.call : the_default
    hash[:description] = the_object.is_a?(Attributor::Dumpable) ? the_object.dump : the_object
  end

  #hash[:examples] = [ example.dump ] if example
  member_example = example && example.first
  hash[:items] = member_attribute.as_json_schema(example: member_example)
  hash
end
check_option!(name, _definition) click to toggle source
# File lib/attributor/types/collection.rb, line 155
def self.check_option!(name, _definition)
  # TODO: support more options like :max_size
  case name
  when :reference
  when :member_options
  else
    return :unknown
  end

  :ok
end
construct(constructor_block, **options) click to toggle source
# File lib/attributor/types/collection.rb, line 139
def self.construct(constructor_block, **options)
  member_options = (options[:member_options] || {}).clone
  if options.key?(:reference) && !member_options.key?(:reference)
    member_options[:reference] = options[:reference]
  end

  # create the member_attribute, passing in our member_type and whatever constructor_block is.
  # that in turn will call construct on the type if applicable.
  @member_attribute = Attributor::Attribute.new member_type, member_options, &constructor_block

  # overwrite our type with whatever type comes out of the attribute
  @member_type = @member_attribute.type

  self
end
constructable?() click to toggle source
# File lib/attributor/types/collection.rb, line 135
def self.constructable?
  true
end
decode_string(value, context) click to toggle source
# File lib/attributor/types/collection.rb, line 96
def self.decode_string(value, context)
  decode_json(value, context)
end
describe(shallow = false, example: nil) click to toggle source
Calls superclass method
# File lib/attributor/types/collection.rb, line 105
def self.describe(shallow = false, example: nil)
  hash = super(shallow)
  hash[:options] = {} unless hash[:options]
  if example
    hash[:example] = example
    member_example = example.first
  end
  hash[:member_attribute] = member_attribute.describe(true, example: member_example)
  hash
end
dump(values, **opts) click to toggle source
# File lib/attributor/types/collection.rb, line 100
def self.dump(values, **opts)
  return nil if values.nil?
  values.collect { |value| member_attribute.dump(value, **opts) }
end
example(context = nil, options: {}) click to toggle source

generates an example Collection @return An Array of native type objects conforming to the specified member_type TODO: ALLOW to pass “values” for the members?…as values: {id: 1, …}

# File lib/attributor/types/collection.rb, line 59
def self.example(context = nil, options: {})
  result = []
  size = options[:size] || (rand(3) + 1)
  size = [*size].sample if size.is_a?(Range)

  context ||= ["Collection-#{result.object_id}"]
  context = Array(context)

  # avoid infinite recursion in example generation
  example_depth = context.size
  size = 0 if example_depth > Hash::MAX_EXAMPLE_DEPTH

  size.times do |i|
    subcontext = context + ["at(#{i})"]
    result << member_attribute.example(subcontext)
  end

  new(result)
end
family() click to toggle source
# File lib/attributor/types/collection.rb, line 40
def self.family
  'array'
end
inherited(klass) click to toggle source
# File lib/attributor/types/collection.rb, line 22
def self.inherited(klass)
  klass.instance_eval do
    @options = {}
  end
end
json_schema_type() click to toggle source
# File lib/attributor/types/collection.rb, line 116
def self.json_schema_type
  :array
end
load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options) click to toggle source

The incoming value should be array-like here, so the only decoding that we need to do is from the members (if there’s an :member_type defined option).

# File lib/attributor/types/collection.rb, line 81
def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
  return nil if value.nil?
  if value.is_a?(Enumerable)
    loaded_value = value
  elsif value.is_a?(::String)
    loaded_value = decode_string(value, context)
  elsif value.respond_to?(:to_a)
    loaded_value = value.to_a
  else
    raise Attributor::IncompatibleTypeError.new(context: context, value_type: value.class, type: self)
  end

  new(loaded_value.collect { |member| member_attribute.load(member, context) })
end
member_attribute() click to toggle source
# File lib/attributor/types/collection.rb, line 48
def self.member_attribute
  @member_attribute ||= begin
    construct(nil)

    @member_attribute
  end
end
member_type() click to toggle source
# File lib/attributor/types/collection.rb, line 44
def self.member_type
  @member_type ||= Attributor::Object
end
native_type() click to toggle source
# File lib/attributor/types/collection.rb, line 32
def self.native_type
  self
end
of(type) click to toggle source

@param type [Attributor::Type] optional, defines the type of all collection members @return anonymous class with specified type of collection members

@example Collection.of(Integer)

# File lib/attributor/types/collection.rb, line 14
def self.of(type)
  # Favor T[] since that even caches the non-construcable types
  resolved_type = Attributor.resolve_type(type)
  resolved_type[self]
end
valid_type?(type) click to toggle source
# File lib/attributor/types/collection.rb, line 36
def self.valid_type?(type)
  type.is_a?(self) || type.is_a?(::Enumerable)
end
validate(object, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil) click to toggle source

@param object [Collection] Collection instance to validate.

# File lib/attributor/types/collection.rb, line 168
def self.validate(object, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil)
  context = [context] if context.is_a? ::String

  unless object.is_a?(self)
    raise ArgumentError, "#{name} can not validate object of type #{object.class.name} for #{Attributor.humanize_context(context)}."
  end

  object.validate(context)
end
validate_options(_value, _context, _attribute) click to toggle source
# File lib/attributor/types/collection.rb, line 178
def self.validate_options(_value, _context, _attribute)
  errors = []
  errors
end

Public Instance Methods

dump(**opts) click to toggle source
# File lib/attributor/types/collection.rb, line 190
def dump(**opts)
  collect { |value| self.class.member_attribute.dump(value, **opts) }
end
validate(context = Attributor::DEFAULT_ROOT_CONTEXT) click to toggle source
# File lib/attributor/types/collection.rb, line 183
def validate(context = Attributor::DEFAULT_ROOT_CONTEXT)
  each_with_index.collect do |value, i|
    subcontext = context + ["at(#{i})"]
    self.class.member_attribute.validate(value, subcontext)
  end.flatten.compact
end