Module: Plumb::Attributes
- Included in:
- Types::Data
- Defined in:
- lib/plumb/attributes.rb
Defined Under Namespace
Modules: ClassMethods
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Returns the value of attribute attributes.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
Class Method Summary collapse
-
.included(base) ⇒ Object
A module that provides a simple way to define a struct-like class with attributes that are type-checked on initialization.
-
.struct_class(node) ⇒ Object
The struct class behind
node, or nil.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #deconstruct ⇒ Object
- #deconstruct_keys ⇒ Object
- #initialize(attrs = {}) ⇒ Object
- #inspect ⇒ Object
- #to_h ⇒ Hash
- #to_hash ⇒ Object
- #valid? ⇒ Boolean
- #with(attrs = BLANK_HASH) ⇒ Plumb::Attributes
Instance Attribute Details
#attributes ⇒ Object (readonly)
Returns the value of attribute attributes.
135 136 137 |
# File 'lib/plumb/attributes.rb', line 135 def attributes @attributes end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
135 136 137 |
# File 'lib/plumb/attributes.rb', line 135 def errors @errors end |
Class Method Details
.included(base) ⇒ Object
A module that provides a simple way to define a struct-like class with attributes that are type-checked on initialization.
It supports nested attributes:
Or arrays of nested attributes:
Or use struct classes defined separately:
Arrays and other types support composition and helpers. Ex. #default.
attribute :companies, Types::Array[Company].default([].freeze)
Passing a named struct class AND a block will subclass the struct and extend it with new attributes:
attribute :company, Company do
attribute :address, String
end
The same works with arrays:
attribute :companies, Types::Array[Company] do
attribute :address, String
end
Note that this does NOT work with union'd or piped structs.
attribute :company, Company | Person do
Optional Attributes
Using attribute? allows for optional attributes. If the attribute is not present, it will be set to Undefined.
attribute? :company, Company
Struct Inheritance
Structs can inherit from other structs. This is useful for defining a base struct with common attributes.
class BasePerson
include Plumb::Attributes
attribute :name, String
end
class Person < BasePerson
attribute :age, Integer
end
[] Syntax
The [] syntax can be used to define a struct in a single line.
Like Plumb::Types::Hash, suffixing a key with ? makes it optional.
Person = Data[name: String, age?: Integer]
person = Person.new(name: 'Jane')
111 112 113 114 |
# File 'lib/plumb/attributes.rb', line 111 def self.included(base) base.send(:extend, ClassMethods) base.define_singleton_method(:__plumb_struct_class__) { base } end |
.struct_class(node) ⇒ Object
The struct class behind node, or nil. Structs appear in two shapes: a
Plumb::Attributes class itself (Types::Data subclasses are Composable
classes), or the Function that Composable.wrap builds around a plain
include Plumb::Attributes class — the class is the wrapped callable, so
it is reached via #fn (a Function's #children are its types). This is the
one owner of that representation fact — used by #build_nested and Codec's
rewriter.
Keyed on Function#wraps_callable? rather than on the types the node declares: boundary absorption can move a neighbouring type into a wrapper's slot (see Function#absorb_input), and it wraps the same class either way.
127 128 129 130 131 132 133 |
# File 'lib/plumb/attributes.rb', line 127 def self.struct_class(node) return node if node.is_a?(::Class) && node <= Attributes return nil unless node.is_a?(Plumb::Function) && node.wraps_callable? callable = node.fn callable.is_a?(::Class) && callable <= Attributes ? callable : nil end |
Instance Method Details
#==(other) ⇒ Object
142 143 144 |
# File 'lib/plumb/attributes.rb', line 142 def ==(other) other.is_a?(self.class) && other.attributes == attributes end |
#deconstruct ⇒ Object
180 |
# File 'lib/plumb/attributes.rb', line 180 def deconstruct(...) = to_h.values.deconstruct(...) |
#deconstruct_keys ⇒ Object
181 |
# File 'lib/plumb/attributes.rb', line 181 def deconstruct_keys(...) = to_h.deconstruct_keys(...) |
#initialize(attrs = {}) ⇒ Object
137 138 139 140 |
# File 'lib/plumb/attributes.rb', line 137 def initialize(attrs = {}) assign_attributes(self.class._pipeline.parse(attrs)) freeze end |
#inspect ⇒ Object
155 156 157 158 159 |
# File 'lib/plumb/attributes.rb', line 155 def inspect %(#<#{self.class}:#{object_id} [#{valid? ? 'valid' : 'invalid'}] #{attributes.map do |k, v| [k, v.inspect].join(':') end.join(' ')}>) end |
#to_h ⇒ Hash
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/plumb/attributes.rb', line 162 def to_h self.class._schema._schema.keys.each.with_object({}) do |key, memo| key = key.to_sym value = attributes[key] val = case value when ::Array value.map { |v| v.respond_to?(:to_h) ? v.to_h : v } when ::NilClass nil else value.respond_to?(:to_h) ? value.to_h : value end memo[key] = val end end |
#to_hash ⇒ Object
178 |
# File 'lib/plumb/attributes.rb', line 178 def to_hash = to_h |
#valid? ⇒ Boolean
147 |
# File 'lib/plumb/attributes.rb', line 147 def valid? = !errors || errors.none? |
#with(attrs = BLANK_HASH) ⇒ Plumb::Attributes
151 152 153 |
# File 'lib/plumb/attributes.rb', line 151 def with(attrs = BLANK_HASH) self.class.new(attributes.merge(attrs)) end |