Module: Striuct::InstanceMethods

Extended by:
Forwardable
Includes:
KeyValidatable
Defined in:
lib/striuct/instancemethods/cast.rb,
lib/striuct/instancemethods/enum.rb,
lib/striuct/instancemethods/lock.rb,
lib/striuct/instancemethods/to_s.rb,
lib/striuct/instancemethods/hashy.rb,
lib/striuct/instancemethods/assign.rb,
lib/striuct/instancemethods/getter.rb,
lib/striuct/instancemethods/object.rb,
lib/striuct/instancemethods/safety.rb,
lib/striuct/instancemethods/setter.rb,
lib/striuct/instancemethods/values.rb,
lib/striuct/instancemethods/compare.rb,
lib/striuct/instancemethods/default.rb,
lib/striuct/instancemethods/validation.rb,
lib/striuct/instancemethods/requirements.rb,
lib/striuct/instancemethods/keyvalidatable.rb,
lib/striuct/instancemethods/delegate_class_methods.rb

Cast collapse

Enumerative collapse

Lock / Unlock collapse

To Strings collapse

Like Ruby's Hash collapse

Assign / Unassign collapse

Getter collapse

Basic Methods for Ruby's Object collapse

Safety collapse

Setter collapse

Behavior under Values collapse

Compare with other collapse

Default Value collapse

Validation collapse

Delegate Class Methods collapse

Instance Method Details

#==(other) ⇒ Boolean Also known as: ===

Returns:

  • (Boolean)


6
7
8
9
# File 'lib/striuct/instancemethods/compare.rb', line 6

def ==(other)
  other.instance_of?(self.class) && 
    each_pair.all?{|autonym, val|other._get(autonym) == val}
end

#[]=(key, value) ⇒ Object Also known as: assign

Returns value.

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • value



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/striuct/instancemethods/setter.rb', line 7

def []=(key, value)
  autonym = autonym_for_key key
  _set autonym, value
rescue Validation::InvalidWritingError
  $!.set_backtrace([
    "#{$!.backtrace[-1].sub(/[^:]+\z/){''}}in `[#{key.inspect}(#{autonym})]=': #{$!.message}",
    $!.backtrace[-1]
  ])

  raise
end

#_autonymsObject (private)



31
32
33
# File 'lib/striuct/instancemethods/delegate_class_methods.rb', line 31

def _autonyms
  self.class.__send__ :_autonyms
end

#_check_frozenObject (private)



50
51
52
# File 'lib/striuct/instancemethods/object.rb', line 50

def _check_frozen
  raise "can't modify frozen #{self.class}" if frozen?
end

#_check_locked(key) ⇒ Object (private)



54
55
56
# File 'lib/striuct/instancemethods/object.rb', line 54

def _check_locked(key)
  raise "can't modify locked member `#{key}`" if locked? key
end

#_check_must(key) ⇒ Object (private)



58
59
60
61
62
# File 'lib/striuct/instancemethods/object.rb', line 58

def _check_must(key)
  if must?(key) && !assigned?(key)
    raise InvalidOperationError, "`#{key}` require a value under `must` option"
  end
end

#_initialize_databaseObject (private)



46
47
48
# File 'lib/striuct/instancemethods/object.rb', line 46

def _initialize_database
  @db, @locks = {}, {}
end

#_set(autonym, value) ⇒ Object (private)

Returns value.

Parameters:

  • autonym (Symbol)
    • MUST already converted to native autonym

Returns:

  • value



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/striuct/instancemethods/setter.rb', line 25

def _set(autonym, value)
  _check_frozen
  _check_locked autonym

  if with_adjuster? autonym
    begin
      value = instance_exec value, &adjuster_for(autonym)
    rescue Exception
      raise ::Validation::UnmanagebleError
    end
  end

  if with_safety_setter?(autonym) and !accept?(autonym, value)
    raise ::Validation::InvalidWritingError,
          "#{value.inspect} is deficient for #{autonym} in #{self.class}"
  end

  @db[autonym] = value
rescue ::Validation::InvalidError
  unless /in \[\]=/ =~ caller[1].slice(/([^:]+)\z/)
    $!.backtrace.delete_if{|s|/#{Regexp.escape(File.dirname __FILE__)}/ =~ s}
    $!.backtrace.first.sub!(/([^:]+)\z/){"in `#{autonym}='"}
  end

  raise
end

#_set_defaults(*target_autonyms) ⇒ self (private)

Parameters:

  • target_autonyms (Symbol)
    • MUST already converted to native autonym

Returns:

  • (self)


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/striuct/instancemethods/default.rb', line 16

def _set_defaults(*target_autonyms)
  target_autonyms.each do |autonym|
    if with_default? autonym
      default = default_value_for autonym
      _set autonym, (
        if default_type_for(autonym) == :lazy
          args = [self, autonym][0, default.arity]
          default.call(*args)
        else
          default
        end
      )
    end
  end
  
  self
end

#accept?(key, value) ⇒ Boolean

true if passed under any condition

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

  • value

Returns:

  • (Boolean)


8
9
10
11
12
13
14
15
16
17
# File 'lib/striuct/instancemethods/validation.rb', line 8

def accept?(key, value)
  autonym = autonym_for_key key
  return true unless restrict? autonym

  begin  
    _valid? condition_for(autonym), value
  rescue Exception
    false
  end
end

#all_locked?Boolean

Returns:

  • (Boolean)


28
29
30
# File 'lib/striuct/instancemethods/lock.rb', line 28

def all_locked?
  _autonyms.all?{|autonym|@locks.has_key? autonym}
end

#assigned?(key) ⇒ Boolean Also known as: assign?

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • (Boolean)


6
7
8
# File 'lib/striuct/instancemethods/assign.rb', line 6

def assigned?(key)
  @db.has_key? autonym_for_key(key)
end

#assoc(name) ⇒ Array

Returns e.g [autonym, value].

Parameters:

  • name (Symbol, String)

Returns:

  • (Array)

    e.g [autonym, value]



79
80
81
82
83
# File 'lib/striuct/instancemethods/hashy.rb', line 79

def assoc(name)
  autonym = autonym_for_member name

  [autonym, self[name]]
end

#default?(key) ⇒ Boolean

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • (Boolean)


6
7
8
9
10
# File 'lib/striuct/instancemethods/default.rb', line 6

def default?(key)
  autonym = autonym_for_key key

  default_value_for(autonym) == fetch_by_autonym(autonym)
end

#delete_if {|autonym, value| ... } ⇒ Enumerator

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Returns:

  • (Enumerator)

See Also:



69
70
71
72
73
74
75
# File 'lib/striuct/instancemethods/hashy.rb', line 69

def delete_if(&block)
  _check_frozen
  return to_enum(__callee__) unless block_given?

  reject!(&block)
  self
end

#each_autonym {|autonym| ... } ⇒ Enumerator Also known as: each_member

Yields:

  • (autonym)

Yield Parameters:

  • autonym (Symbol)
    • sequential under defined

Yield Returns:

  • (self)

Returns:

  • (Enumerator)


9
10
11
12
13
14
# File 'lib/striuct/instancemethods/enum.rb', line 9

def each_autonym(&block)
  return to_enum(__callee__) { self.class.size } unless block_given?

  self.class.each_autonym(&block)
  self
end

#each_autonym_with_index {|autonym, index| ... } ⇒ Enumerator Also known as: each_member_with_index

Yields:

  • (autonym, index)

Yield Parameters:

  • autonym (Symbol)
  • index (Integer)

Yield Returns:

  • (self)

Returns:

  • (Enumerator)


60
61
62
63
64
65
# File 'lib/striuct/instancemethods/enum.rb', line 60

def each_autonym_with_index
  return to_enum(__callee__) { self.class.size } unless block_given?

  self.class.each_autonym_with_index{|autonym, index|yield autonym, index}
  self
end

#each_index {|index| ... } ⇒ Enumerator

Yields:

  • (index)

Yield Parameters:

  • index (Integer)

Yield Returns:

  • (self)

Returns:

  • (Enumerator)


48
49
50
51
52
53
# File 'lib/striuct/instancemethods/enum.rb', line 48

def each_index
  return to_enum(__callee__) { self.class.size } unless block_given?

  self.class.each_index{|index|yield index}
  self
end

#each_pair {|autonym, value| ... } ⇒ Enumerator

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)
  • value (Object)

Yield Returns:

  • (self)

Returns:

  • (Enumerator)

See Also:



38
39
40
41
42
# File 'lib/striuct/instancemethods/enum.rb', line 38

def each_pair
  return to_enum(__callee__) { self.class.size } unless block_given?

  each_autonym{|autonym|yield autonym, _get(autonym)}
end

#each_pair_with_index {|autonym, value, index| ... } ⇒ Enumerator

Yields:

  • (autonym, value, index)

Yield Parameters:

  • autonym (Symbol)
  • index (Integer)

Yield Returns:

  • (self)

Returns:

  • (Enumerator)


86
87
88
89
90
91
92
93
94
# File 'lib/striuct/instancemethods/enum.rb', line 86

def each_pair_with_index
  return to_enum(__callee__) { self.class.size } unless block_given?

  index = 0
  each_pair do |autonym, value|
    yield autonym, value, index
    index += 1
  end
end

#each_value {|value| ... } ⇒ Enumerator Also known as: each

Yields:

  • (value)

Yield Parameters:

  • value (Object)
    • sequential under defined

Yield Returns:

  • (self)

Returns:

  • (Enumerator)

See Also:



23
24
25
26
27
# File 'lib/striuct/instancemethods/enum.rb', line 23

def each_value
  return to_enum(__callee__) { self.class.size } unless block_given?

  each_autonym{|autonym|yield _get(autonym)}
end

#each_value_with_index {|value, index| ... } ⇒ Enumerator Also known as: each_with_index

Yields:

  • (value, index)

Yield Parameters:

  • index (Integer)

Yield Returns:

  • (self)

Returns:

  • (Enumerator)


73
74
75
76
77
# File 'lib/striuct/instancemethods/enum.rb', line 73

def each_value_with_index
  return to_enum(__callee__) { self.class.size } unless block_given?

  each_value.with_index{|value, index|yield value, index}
end

#empty?Boolean

true if all members are not yet assigned

Returns:

  • (Boolean)


27
28
29
# File 'lib/striuct/instancemethods/assign.rb', line 27

def empty?
  _autonyms.none?{|autonym|@db.has_key? autonym}
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


13
14
15
# File 'lib/striuct/instancemethods/compare.rb', line 13

def eql?(other)
  other.instance_of?(self.class) && other._db.eql?(@db)
end

#fetch_by_autonym(autonym) ⇒ Object

Parameters:

  • autonym (Symbol, String, #to_sym)

Raises:

  • (NameError)


6
7
8
9
10
11
# File 'lib/striuct/instancemethods/getter.rb', line 6

def fetch_by_autonym(autonym)
  autonym = autonym.to_sym
  raise NameError unless autonym? autonym

  _get autonym
end

#fetch_by_index(index) ⇒ Object

Parameters:

  • index (Integer, #to_int)


19
20
21
# File 'lib/striuct/instancemethods/getter.rb', line 19

def fetch_by_index(index)
  _get autonym_for_index(index)
end

#fetch_by_key(key) ⇒ Object Also known as: [], fetch

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index



24
25
26
# File 'lib/striuct/instancemethods/getter.rb', line 24

def fetch_by_key(key)
  _get autonym_for_key(key)
end

#fetch_by_member(member) ⇒ Object

Parameters:

  • member (Symbol, String, #to_sym)


14
15
16
# File 'lib/striuct/instancemethods/getter.rb', line 14

def fetch_by_member(member)
  _get autonym_for_member(member)
end

#fetch_values(*_keys, &block) ⇒ Array

Returns:

  • (Array)

Raises:

  • (ArgumentError)

    if the keys contains an unmacthed key and no block is given



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/striuct/instancemethods/values.rb', line 29

def fetch_values(*_keys, &block)
  _keys.map {|key|
    if has_key? key
      fetch_by_key(key)
    else
      if block_given?
        block.call
      else
        raise ArgumentError, "`#{key}' is not matched"
      end
    end
  }
end

#flatten(level = 1) ⇒ Array

Returns:

  • (Array)

See Also:

  • Hash#flatten


92
93
94
# File 'lib/striuct/instancemethods/hashy.rb', line 92

def flatten(level=1)
  each_pair.to_a.flatten level
end

#freezeself

Returns:

  • (self)


6
7
8
9
# File 'lib/striuct/instancemethods/object.rb', line 6

def freeze
  @db.freeze; @locks.freeze
  super
end

#has_value?(value) ⇒ Boolean Also known as: value?

Returns:

  • (Boolean)


5
6
7
# File 'lib/striuct/instancemethods/hashy.rb', line 5

def has_value?(value)
  @db.has_value? value
end

#hashInteger

Returns:

  • (Integer)


18
19
20
# File 'lib/striuct/instancemethods/compare.rb', line 18

def hash
  @db.hash
end

#initialize(*values) ⇒ Object (private)



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/striuct/instancemethods/object.rb', line 13

def initialize(*values)
  _initialize_database

  replace_values(*values)
  excess_autonyms = _autonyms.last(size - values.size)
  _set_defaults(*excess_autonyms)

  each_autonym do |autonym|
    _check_must autonym
  end
end

#initialize_copy(original) ⇒ Object (private)



42
43
44
# File 'lib/striuct/instancemethods/object.rb', line 42

def initialize_copy(original)
  @db, @locks = @db.dup, {}
end

#initialize_for_pairs(pairs) ⇒ Object (private)



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/striuct/instancemethods/object.rb', line 25

def initialize_for_pairs(pairs)
  _initialize_database
  
  excess_autonyms = _autonyms.dup
  pairs.each_pair do |key, value|
    autonym = autonym_for_key key
    self[autonym] = value
    excess_autonyms.delete autonym
  end

  _set_defaults(*excess_autonyms)

  excess_autonyms.each do |autonym|
    _check_must autonym
  end
end

#inspectString

Returns:

  • (String)


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/striuct/instancemethods/to_s.rb', line 6

def inspect
  "#<struct' #{self.class}".tap {|s|
    each_pair do |autonym, value|
      suffix = (with_default?(autonym) && default?(autonym)) ? '/default' : nil
      label_valid = valid?(autonym) ? nil : :invalid
      label_lock = locked?(autonym) ? :locked : nil
      label_must = must?(autonym) ? :must : nil
      labels = [label_valid, label_lock, label_must].select{|_|_}

      s << " #{autonym}=#{value.inspect}#{suffix}"
      unless labels.empty?
        s << '('
        s << labels.join(', ')
        s << ')'
      end
      s << ','
    end
    
    s.chop!
    s << '>'
  }
end

#keep_if {|autonym, value| ... } ⇒ Enumerator

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Returns:

  • (Enumerator)

See Also:



37
38
39
40
41
42
43
# File 'lib/striuct/instancemethods/hashy.rb', line 37

def keep_if(&block)
  _check_frozen
  return to_enum(__callee__) unless block_given?

  select!(&block)
  self
end

#lock(key) ⇒ self

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • (self)


7
8
9
10
11
12
# File 'lib/striuct/instancemethods/lock.rb', line 7

def lock(key)
  _check_frozen

  @locks[autonym_for_key(key)] = true
  self
end

#lock_allself

Returns:

  • (self)


15
16
17
18
19
20
21
# File 'lib/striuct/instancemethods/lock.rb', line 15

def lock_all
  _check_frozen
  
  each_autonym do |autonym|
    @locks[autonym] = true
  end
end

#locked?(key) ⇒ Boolean

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • (Boolean)


24
25
26
# File 'lib/striuct/instancemethods/lock.rb', line 24

def locked?(key)
  @locks.has_key? autonym_for_key(key)
end

#rassoc(value) ⇒ Array

Returns [autonym, value].

Returns:

  • (Array)
    autonym, value


86
87
88
# File 'lib/striuct/instancemethods/hashy.rb', line 86

def rassoc(value)
  each_pair.find{|_, val|val == value}
end

#reject {|autonym, value| ... } ⇒ Striuct

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Returns:

See Also:



110
111
112
113
114
# File 'lib/striuct/instancemethods/hashy.rb', line 110

def reject(&block)
  return to_enum(__callee__) unless block_given?

  dup.tap {|r|r.reject!(&block)}
end

#reject! {|autonym, value| ... } ⇒ Enumerator

keep falsy only (unassign truthy member)

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Returns:

  • (Enumerator)

See Also:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/striuct/instancemethods/hashy.rb', line 50

def reject!
  _check_frozen
  return to_enum(__callee__) unless block_given?

  modified = false
  each_pair do |autonym, value|
    if yield autonym, value
      unassign autonym
      modified = true
    end
  end
  
  modified ? self : nil
end

#replace_values(*values) ⇒ self

Returns:

  • (self)


44
45
46
47
48
49
50
51
52
53
54
# File 'lib/striuct/instancemethods/values.rb', line 44

def replace_values(*values)
  unless values.size <= size
    raise ArgumentError, "struct size differs (max: #{size})"
  end

  values.each_with_index do |value, index|
    _set autonym_for_index(index), value
  end
  
  self
end

#secure?Boolean

freezed, fixed familar members, all members passed any condition

Returns:

  • (Boolean)


6
7
8
# File 'lib/striuct/instancemethods/safety.rb', line 6

def secure?
  (frozen? || all_locked?) && self.class.closed? && strict?
end

#select {|autonym, value| ... } ⇒ Striuct

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Returns:

See Also:



100
101
102
103
104
# File 'lib/striuct/instancemethods/hashy.rb', line 100

def select(&block)
  return to_enum(__callee__) unless block_given?

  dup.tap {|r|r.select!(&block)}
end

#select! {|autonym, value| ... } ⇒ Enumerator

keep truthy only (unassign falsy member)

Yields:

  • (autonym, value)

Yield Parameters:

  • autonym (Symbol)

Yield Returns:

  • (self)
  • (nil)

Returns:

  • (Enumerator)

See Also:



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/striuct/instancemethods/hashy.rb', line 18

def select!
  _check_frozen
  return to_enum(__callee__) unless block_given?

  modified = false
  each_pair do |autonym, value|
    unless yield autonym, value
      unassign autonym
      modified = true
    end
  end
  
  modified ? self : nil
end

#strict?Boolean

all members passed under any condition

Returns:

  • (Boolean)


29
30
31
# File 'lib/striuct/instancemethods/validation.rb', line 29

def strict?
  each_pair.all?{|autonym, value|sufficient? autonym, value}
end

#sufficient?(key, value = self[key]) ⇒ Boolean Also known as: valid?

true if passed under any condition

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

  • value (defaults to: self[key])
    • if no argument and use current assigned value

Returns:

  • (Boolean)


22
23
24
# File 'lib/striuct/instancemethods/validation.rb', line 22

def sufficient?(key, value=self[key])
  accept? key, value
end

#to_h(include_no_assign = true) ⇒ Hash

Parameters:

  • include_no_assign (Boolean) (defaults to: true)

Returns:

  • (Hash)


17
18
19
20
21
# File 'lib/striuct/instancemethods/cast.rb', line 17

def to_h(include_no_assign=true)
  return @db.dup unless include_no_assign

  Hash[each_pair.to_a]
end

#to_sString

Returns:

  • (String)


30
31
32
33
34
35
36
37
38
39
# File 'lib/striuct/instancemethods/to_s.rb', line 30

def to_s
  "#<struct' #{self.class}".tap {|s|
    each_pair do |autonym, value|
      s << " #{autonym}=#{value.inspect},"
    end
    
    s.chop!
    s << '>'
  }
end

#to_striuctself

Returns:

  • (self)


6
7
8
# File 'lib/striuct/instancemethods/cast.rb', line 6

def to_striuct
  self
end

#to_structStruct

Returns:

  • (Struct)


11
12
13
# File 'lib/striuct/instancemethods/cast.rb', line 11

def to_struct
  self.class.to_struct_class.new(*values)
end

#unassign(key) ⇒ Object Also known as: delete_at

Returns value / nil - value assigned under the key.

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • value / nil - value assigned under the key



14
15
16
17
18
19
20
21
22
# File 'lib/striuct/instancemethods/assign.rb', line 14

def unassign(key)
  _check_frozen
  _check_locked key
  if must? key
    raise InvalidOperationError, "`#{key}` require a value under `must` option"
  end
  
  @db.delete autonym_for_key(key)
end

#unlock(key) ⇒ self (private)

Parameters:

  • key (Symbol, String, #to_sym, Integer, #to_int)
    • name / index

Returns:

  • (self)


36
37
38
39
40
41
# File 'lib/striuct/instancemethods/lock.rb', line 36

def unlock(key)
  _check_frozen

  @locks.delete autonym_for_key(key)
  self
end

#unlock_allself (private)

Returns:

  • (self)


44
45
46
47
48
49
# File 'lib/striuct/instancemethods/lock.rb', line 44

def unlock_all
  _check_frozen

  @locks.clear
  self
end

#valuesArray Also known as: to_a

Returns:

  • (Array)


24
25
26
# File 'lib/striuct/instancemethods/cast.rb', line 24

def values
  each_value.to_a
end

#values_at(*_keys) ⇒ Array

Parameters:

  • _keys (Integer, #to_int, Range)

Returns:

  • (Array)


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/striuct/instancemethods/values.rb', line 7

def values_at(*_keys)
  [].tap {|r|
    _keys.each do |key|
      case key
      when ->v{v.respond_to? :to_int}
        r << fetch_by_index(key)
      when Range
        key.each do |idx|
          raise TypeError unless idx.respond_to? :to_int

          r << fetch_by_index(idx)
        end
      else
        raise TypeError
      end
    end
  }
end