class Typed::Struct
Public Class Methods
allow_extra_keys(new_flag)
click to toggle source
# File lib/typed/struct.rb, line 53 def allow_extra_keys(new_flag) define_singleton_method(:allow_extra_keys?) { new_flag } end
allow_extra_keys?()
click to toggle source
# File lib/typed/struct.rb, line 57 def allow_extra_keys? true end
attribute(name, type = Typed.any)
click to toggle source
# File lib/typed/struct.rb, line 36 def attribute(name, type = Typed.any) expected_type(type) name = name.to_sym raise Typed::InvalidType, "Property already defined: #{name}" if typed_attributes.key?(name) typed_attributes[name] = type define_method(name) { @_data.fetch(name) { Typed::Undefined } } end
new(input_data = {})
click to toggle source
# File lib/typed/struct.rb, line 142 def initialize(input_data = {}) case input_data when Typed::Builder::Result then initialize_from_result(input_data) else initialize_from_result(self.class.parse_as_hash(input_data)) end end
parse_as_hash(input_data)
click to toggle source
# File lib/typed/struct.rb, line 70 def parse_as_hash(input_data) return Typed::Builder::Result.success(input_data.to_h) if input_data.is_a?(self) # TODO: remove this hack unless input_data.is_a?(::Hash) || input_data.class.name == 'ActionController::Parameters' return Typed::Builder::Result.failure { "Expected Hash, got #{input_data.inspect}" } end # Start by creating a new "clean" hash from input # This way, we can easily handle some variants (ActionController::Parameters, ...) clean_data = Hash.new { ::Typed::Undefined } input_data.each { |key, value| clean_data[key.to_sym] = value } # Check presence of extra keys extra_property = (clean_data.keys - schema.keys).first if extra_property && !allow_extra_keys? return Typed::Builder::Result .failure("Unknown property '#{extra_property}' of #{inspect}") end # Construct the final hash which will be stored internally to represent # Struct's data. output = schema.each_with_object({}) { |(name, type), acc| result = type.process(clean_data[name]) unless result.ok return Typed::Builder::Result.failure { "Invalid property '#{name}' of #{inspect}: #{result.message}" } end acc[name] = result.value unless Typed::Undefined.equal?(result.value) }.freeze Typed::Builder::Result.success(output) end
process(data)
click to toggle source
# File lib/typed/struct.rb, line 65 def process(data) result = parse_as_hash(data) result.ok ? Typed::Builder::Result.success(new(result)) : result end
schema()
click to toggle source
# File lib/typed/struct.rb, line 47 def schema @schema ||= ancestors.select { |a| Typed::Struct > a }.reverse.reduce({}) { |acc, clazz| acc.merge(clazz.typed_attributes) }.freeze end
typed_attributes()
click to toggle source
# File lib/typed/struct.rb, line 61 def typed_attributes @typed_attributes ||= {} end
Public Instance Methods
==(other)
click to toggle source
# File lib/typed/struct.rb, line 127 def ==(other) return true if other.equal?(self) return false unless other.instance_of?(self.class) @_data == other.instance_variable_get(:@_data) end
[](key)
click to toggle source
# File lib/typed/struct.rb, line 121 def [](key) raise Typed::InvalidType, "Unknown property: #{key.inspect}" unless self.class.schema.key?(key) @_data.fetch(key) { Typed::Undefined } end
hash()
click to toggle source
# File lib/typed/struct.rb, line 134 def hash @_data.hash end
inspect()
click to toggle source
# File lib/typed/struct.rb, line 112 def inspect attrs = self.class.schema.keys.map { |key| " #{key}=#{@_data[key].inspect}" }.join "#<#{self.class.name || self.class.inspect}#{attrs}>" end
key?(key)
click to toggle source
# File lib/typed/struct.rb, line 138 def key?(key) @_data.key?(key) end
to_h()
click to toggle source
# File lib/typed/struct.rb, line 117 def to_h @_data end
updater(target)
click to toggle source
# File lib/typed/struct.rb, line 108 def updater(target) Updater.new(target, self) end
Private Instance Methods
initialize_from_result(result)
click to toggle source
# File lib/typed/struct.rb, line 151 def initialize_from_result(result) raise Typed::InvalidValue, result.message unless result.ok @_data = result.value end