class Evil::Struct

Nested structure with type constraints, based on the `dry-initializer` DSL

Public Class Methods

[](value = {})
Alias for: new
attribute(name, type = nil, as: nil, **opts)
Alias for: option
attributes(**options, &block) click to toggle source

@!method attributes(options) Shares options between definitions made inside the block

@example

attributes optional: true do
  attribute :foo
  attribute :bar
end

@option options (see attribute) @return [self] itself

# File lib/evil/struct.rb, line 48
def attributes(**options, &block)
  Attributes.call(self, options, &block)
  self
end
call(value = {})
Alias for: new
list_of_attributes() click to toggle source

Returns the list of defined attributes

@return [Array<Symbol>]

# File lib/evil/struct.rb, line 57
def list_of_attributes
  @list_of_attributes ||= []
end
load(value = {})
Alias for: new
new(value = {}) click to toggle source

Builds a struct from value that respond to `to_h` or `to_hash`

@param [#to_h, to_hash] value (nil) @return [Evil::Struct]

@alias :call @alias :[] @alias :load

Calls superclass method
# File lib/evil/struct.rb, line 20
def new(value = {})
  value if value.instance_of? self.class

  hash = value           if value.is_a? Hash
  hash ||= value.to_h    if value.respond_to? :to_h
  hash ||= value.to_hash if value.respond_to? :to_hash

  hash_with_symbolic_keys = hash.each_with_object({}) do |(key, val), obj|
    obj[key.to_sym] = val
  end
  super hash_with_symbolic_keys
end
Also aliased as: call, [], load
option(name, type = nil, as: nil, **opts) click to toggle source

@!method attribute(name, type = nil, options) Declares the attribute

@param [#to_sym] name The name of the key @param [#call] type (nil) The type constraint @option options [#call] :type Type constraint (alternative syntax) @option options [#to_sym] :as The name of the attribute @option options [Proc] :default Block returning a default value @option options [Boolean] :optional (nil) Whether key is optional @return [self]

@alias :option @alias :param

Calls superclass method
# File lib/evil/struct.rb, line 75
def option(name, type = nil, as: nil, **opts)
  super.tap { list_of_attributes << (as || name).to_sym }
  self
end
Also aliased as: attribute, param
param(name, type = nil, as: nil, **opts)
Alias for: option

Private Class Methods

inherited(klass) click to toggle source
Calls superclass method
# File lib/evil/struct.rb, line 84
def inherited(klass)
  super
  klass.instance_variable_set :@list_of_attributes, list_of_attributes.dup
end

Public Instance Methods

==(other) click to toggle source

Checks an equality to other object that respond to `to_h` or `to_hash`

@param [Object] other @return [Boolean]

# File lib/evil/struct.rb, line 95
def ==(other)
  if other&.respond_to?(:to_h)
    to_h == other.to_h
  elsif other.respond_to?(:to_hash)
    to_h == other.to_hash
  else
    false
  end
end
deep_merge(other)
Alias for: merge_deeply
dump()
Alias for: to_h
merge(other) click to toggle source

Shallowly merges other object to the current struct

@example

class User < Evil::Struct
  attribute :name
  attribute :age
end
joe_at_3 = User.new(name: "Joe", age: 3)

joe_at_4 = joe_at_3.merge(age: 4)
joe_at_4.name # => "Joe"
joe_at_4.age  # => 4

@param [Hash, to_h, to_hash] other @return [self.class] new instance of the current class

# File lib/evil/struct.rb, line 159
def merge(other)
  self.class[Utils.merge(to_h, other)]
end
merge_deeply(other) click to toggle source

Deeply merges other object to the current struct

It iterates through hashes and objects responding to `to_h` and `to_hash`. The iteration stops when any non-hash value reached.

@example

class User < Evil::Struct
  attribute :info
  attribute :meta
end
user = User.new info: { names: [{ first: "Joe", last: "Doe" }], age: 33 },
                meta: { type:  :admin }

user.merge info: { names: [{ first: "John" }] }, meta: { "role" => :cto }
user.to_h # => {
          #      info: { names: [{ first: "John" }], age: 33 },
          #      meta: { type: :admin, role: :cto }
          #    }

@param [Hash, to_h, to_hash] other @return [self.class] new instance of the current class

@alias :deep_merge

# File lib/evil/struct.rb, line 187
def merge_deeply(other)
  self.class[Utils.merge_deeply(self, other)]
end
Also aliased as: deep_merge
to_h() click to toggle source

Converts nested structure to hash

Makes conversion through nested hashes, arrays, enumerables, as well as trhough values that respond to `to_a`, `to_h`, and `to_hash`. Doesn't convert `nil`.

@return [Hash]

@alias :to_hash @alias :dump

# File lib/evil/struct.rb, line 116
def to_h
  self.class.list_of_attributes.each_with_object({}) do |key, hash|
    val = instance_variable_get :"@#{key}"
    hash[key] = Utils.hashify(val) unless val == Dry::Initializer::UNDEFINED
  end
end
Also aliased as: to_hash, dump
to_hash()
Alias for: to_h