Class: Attributor::Collection
- Inherits:
-
Array
- Object
- Array
- Attributor::Collection
- Defined in:
- lib/attributor/types/collection.rb
Direct Known Subclasses
Class Attribute Summary collapse
-
.options ⇒ Object
readonly
Returns the value of attribute options.
Class Method Summary collapse
- .as_json_schema(shallow: false, example: nil, attribute_options: {}) ⇒ Object
- .check_option!(name, _definition) ⇒ Object
- .construct(constructor_block, **options) ⇒ Object
- .constructable? ⇒ Boolean
- .decode_string(value, context) ⇒ Object
- .describe(shallow = false, example: nil) ⇒ Object
- .dump(values, **opts) ⇒ Object
-
.example(context = nil, options: {}) ⇒ Object
generates an example Collection TODO: ALLOW to pass “values” for the members?…as values: 1, ….
- .family ⇒ Object
- .inherited(klass) ⇒ Object
- .json_schema_type ⇒ Object
-
.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options) ⇒ Object
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).
- .member_attribute ⇒ Object
- .member_type ⇒ Object
- .native_type ⇒ Object
-
.of(type) ⇒ Object
Anonymous class with specified type of collection members.
- .valid_type?(type) ⇒ Boolean
- .validate(object, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil) ⇒ Object
- .validate_options(_value, _context, _attribute) ⇒ Object
Instance Method Summary collapse
Methods included from Container
Class Attribute Details
.options ⇒ Object (readonly)
Returns the value of attribute options.
33 34 35 |
# File 'lib/attributor/types/collection.rb', line 33 def @options end |
Class Method Details
.as_json_schema(shallow: false, example: nil, attribute_options: {}) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/attributor/types/collection.rb', line 124 def self.as_json_schema( shallow: false, example: nil, attribute_options: {} ) hash = super opts = self..merge( ) 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) ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/attributor/types/collection.rb', line 159 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) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/attributor/types/collection.rb', line 143 def self.construct(constructor_block, **) = ([:member_options] || {}).clone if .key?(:reference) && !.key?(:reference) [:reference] = [: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, , &constructor_block # overwrite our type with whatever type comes out of the attribute @member_type = @member_attribute.type self end |
.constructable? ⇒ Boolean
139 140 141 |
# File 'lib/attributor/types/collection.rb', line 139 def self.constructable? true end |
.decode_string(value, context) ⇒ Object
100 101 102 |
# File 'lib/attributor/types/collection.rb', line 100 def self.decode_string(value, context) decode_json(value, context) end |
.describe(shallow = false, example: nil) ⇒ Object
109 110 111 112 113 114 115 116 117 118 |
# File 'lib/attributor/types/collection.rb', line 109 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) ⇒ Object
104 105 106 107 |
# File 'lib/attributor/types/collection.rb', line 104 def self.dump(values, **opts) return nil if values.nil? values.collect { |value| member_attribute.dump(value, **opts) } end |
.example(context = nil, options: {}) ⇒ Object
generates an example Collection TODO: ALLOW to pass “values” for the members?…as values: 1, …
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/attributor/types/collection.rb', line 63 def self.example(context = nil, options: {}) result = [] size = [: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 ⇒ Object
44 45 46 |
# File 'lib/attributor/types/collection.rb', line 44 def self.family 'array' end |
.inherited(klass) ⇒ Object
26 27 28 29 30 |
# File 'lib/attributor/types/collection.rb', line 26 def self.inherited(klass) klass.instance_eval do @options = {} end end |
.json_schema_type ⇒ Object
120 121 122 |
# File 'lib/attributor/types/collection.rb', line 120 def self.json_schema_type :array end |
.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options) ⇒ Object
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).
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/attributor/types/collection.rb', line 85 def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **) 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 ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/attributor/types/collection.rb', line 52 def self.member_attribute @member_attribute ||= begin construct(nil) @member_attribute end end |
.member_type ⇒ Object
48 49 50 |
# File 'lib/attributor/types/collection.rb', line 48 def self.member_type @member_type ||= Attributor::Object end |
.native_type ⇒ Object
36 37 38 |
# File 'lib/attributor/types/collection.rb', line 36 def self.native_type self end |
.of(type) ⇒ Object
Returns anonymous class with specified type of collection members.
14 15 16 17 18 19 20 21 22 |
# File 'lib/attributor/types/collection.rb', line 14 def self.of(type) resolved_type = Attributor.resolve_type(type) unless resolved_type.ancestors.include?(Attributor::Type) raise Attributor::AttributorException, 'Collections can only have members that are Attributor::Types' end ::Class.new(self) do @member_type = resolved_type end end |
.valid_type?(type) ⇒ Boolean
40 41 42 |
# File 'lib/attributor/types/collection.rb', line 40 def self.valid_type?(type) type.is_a?(self) || type.is_a?(::Enumerable) end |
.validate(object, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil) ⇒ Object
172 173 174 175 176 177 178 179 180 |
# File 'lib/attributor/types/collection.rb', line 172 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) ⇒ Object
182 183 184 185 |
# File 'lib/attributor/types/collection.rb', line 182 def self.(_value, _context, _attribute) errors = [] errors end |
Instance Method Details
#dump(**opts) ⇒ Object
194 195 196 |
# File 'lib/attributor/types/collection.rb', line 194 def dump(**opts) collect { |value| self.class.member_attribute.dump(value, **opts) } end |
#validate(context = Attributor::DEFAULT_ROOT_CONTEXT) ⇒ Object
187 188 189 190 191 192 |
# File 'lib/attributor/types/collection.rb', line 187 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 |