module Striuct::InstanceMethods
Public Class Methods
# File lib/striuct/instancemethods/object.rb, line 15 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
Public Instance Methods
@return [Boolean]
# File lib/striuct/instancemethods/compare.rb, line 8 def ==(other) other.instance_of?(self.class) && each_pair.all? { |autonym, val| other._get(autonym) == val } end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return value
# File lib/striuct/instancemethods/setter.rb, line 9 def []=(key, value) autonym = autonym_for_key(key) _set(autonym, value) rescue InvalidWritingError $!.set_backtrace( ["#{$!.backtrace[-1].sub(/[^:]+\z/) { '' }}in `[#{key.inspect}(#{autonym})]=': #{$!.message}", $!.backtrace[-1]] ) raise end
@param [Proc, Method, ===
] pattern @param [Object] value
# File lib/striuct/instancemethods/validation.rb, line 9 def _valid?(pattern, value) !!( case pattern when Proc instance_exec(value, &pattern) when Method pattern.call(value) else pattern === value end ) end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @param value true if passed under any condition
# File lib/striuct/instancemethods/validation.rb, line 25 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
# File lib/striuct/instancemethods/lock.rb, line 30 def all_locked? _autonyms.all? { |autonym| @locks.key?(autonym) } end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index
# File lib/striuct/instancemethods/assign.rb, line 8 def assigned?(key) @db.key?(autonym_for_key(key)) end
@param [Symbol, String] name @return [Array] e.g [autonym, value]
# File lib/striuct/instancemethods/hashy.rb, line 81 def assoc(name) autonym = autonym_for_member(name) [autonym, self[name]] end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index
# File lib/striuct/instancemethods/default.rb, line 8 def default?(key) autonym = autonym_for_key(key) default_value_for(autonym) == fetch_by_autonym(autonym) end
@see reject!
@yield [autonym, value] @yieldparam [Symbol] autonym @return [Enumerator]
# File lib/striuct/instancemethods/hashy.rb, line 71 def delete_if(&block) _check_frozen return to_enum(__callee__) unless block reject!(&block) self end
@yield [autonym] @yieldparam [Symbol] autonym - sequential under defined @yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 11 def each_autonym(&block) return to_enum(__callee__) { self.class.size } unless block self.class.each_autonym(&block) self end
@yield [autonym, index] @yieldparam [Symbol] autonym @yieldparam [Integer] index @yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 62 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
@yield [index] @yieldparam [Integer] index @yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 50 def each_index return to_enum(__callee__) { self.class.size } unless block_given? self.class.each_index { |index| yield index } self end
@yield [autonym, value] @yieldparam [Symbol] autonym @yieldparam [Object] value @yieldreturn [self] @return [Enumerator] @see each_autonym
@see each_value
# File lib/striuct/instancemethods/enum.rb, line 40 def each_pair return to_enum(__callee__) { self.class.size } unless block_given? each_autonym { |autonym| yield autonym, _get(autonym) } end
@yield [autonym, value, index] @yieldparam [Symbol] autonym @yieldparam [Integer] index @yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 88 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
@yield [value] @yieldparam [Object] value - sequential under defined @see each_autonym
@yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 25 def each_value return to_enum(__callee__) { self.class.size } unless block_given? each_autonym { |autonym| yield _get(autonym) } end
@yield [value, index] @yieldparam [Integer] index @yieldreturn [self] @return [Enumerator]
# File lib/striuct/instancemethods/enum.rb, line 75 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
true if all members are not yet assigned
# File lib/striuct/instancemethods/assign.rb, line 29 def empty? _autonyms.none? { |autonym| @db.key?(autonym) } end
# File lib/striuct/instancemethods/compare.rb, line 15 def eql?(other) other.instance_of?(self.class) && other._db.eql?(@db) end
@param [Symbol, String, to_sym] autonym
# File lib/striuct/instancemethods/getter.rb, line 8 def fetch_by_autonym(autonym) autonym = autonym.to_sym raise NameError unless autonym?(autonym) _get(autonym) end
@param [Integer, to_int] index
# File lib/striuct/instancemethods/getter.rb, line 21 def fetch_by_index(index) _get(autonym_for_index(index)) end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index
# File lib/striuct/instancemethods/getter.rb, line 26 def fetch_by_key(key) _get(autonym_for_key(key)) end
@param [Symbol, String, to_sym] member
# File lib/striuct/instancemethods/getter.rb, line 16 def fetch_by_member(member) _get(autonym_for_member(member)) end
@return [Array] @raise [ArgumentError] if the keys contains an unmatched
key and no block is given
# File lib/striuct/instancemethods/values.rb, line 31 def fetch_values(*keys, &block) keys.map { |key| if key?(key) fetch_by_key(key) else if block yield else raise ArgumentError, "`#{key}' is not matched" end end } end
@see Hash#flatten @return [Array]
# File lib/striuct/instancemethods/hashy.rb, line 94 def flatten(level=1) each_pair.to_a.flatten(level) end
@return [self]
# File lib/striuct/instancemethods/object.rb, line 8 def freeze @db.freeze; @locks.freeze super end
@group Like Ruby's Hash
# File lib/striuct/instancemethods/hashy.rb, line 7 def has_value?(value) @db.value?(value) end
@return [Integer]
# File lib/striuct/instancemethods/compare.rb, line 20 def hash @db.hash end
@return [String]
# File lib/striuct/instancemethods/to_s.rb, line 8 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 { |elm| elm } s << " #{autonym}=#{value.inspect}#{suffix}" unless labels.empty? s << '(' s << labels.join(', ') s << ')' end s << ',' end s.chop! s << '>' } end
@see select!
@yield [autonym, value] @yieldparam [Symbol] autonym @return [Enumerator]
# File lib/striuct/instancemethods/hashy.rb, line 39 def keep_if(&block) _check_frozen return to_enum(__callee__) unless block select!(&block) self end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return [self]
# File lib/striuct/instancemethods/lock.rb, line 9 def lock(key) _check_frozen @locks[autonym_for_key(key)] = true self end
@return [self]
# File lib/striuct/instancemethods/lock.rb, line 17 def lock_all _check_frozen each_autonym do |autonym| @locks[autonym] = true end end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index
# File lib/striuct/instancemethods/lock.rb, line 26 def locked?(key) @locks.key?(autonym_for_key(key)) end
@return [Array] [autonym, value]
# File lib/striuct/instancemethods/hashy.rb, line 88 def rassoc(value) each_pair.find { |_, val| val == value } end
@see reject!
@yield [autonym, value] @yieldparam [Symbol] autonym @return [Striuct]
# File lib/striuct/instancemethods/hashy.rb, line 112 def reject(&block) return to_enum(__callee__) unless block dup.tap { |r| r.reject!(&block) } end
@see select!
keep falsy only (unassign truthy member) @yield [autonym, value] @yieldparam [Symbol] autonym @return [Enumerator]
# File lib/striuct/instancemethods/hashy.rb, line 52 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
@return [self]
# File lib/striuct/instancemethods/values.rb, line 46 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
freezed, fixed familiar members, all members passed any condition
# File lib/striuct/instancemethods/safety.rb, line 8 def secure? (frozen? || all_locked?) && self.class.closed? && strict? end
@see select!
@yield [autonym, value] @yieldparam [Symbol] autonym @return [Striuct]
# File lib/striuct/instancemethods/hashy.rb, line 102 def select(&block) return to_enum(__callee__) unless block dup.tap { |r| r.select!(&block) } end
keep truthy only (unassign falsy member) @yield [autonym, value] @yieldparam [Symbol] autonym @see each_pair
@return [Enumerator] @yieldreturn [self] @yieldreturn [nil]
# File lib/striuct/instancemethods/hashy.rb, line 20 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
all members passed under any condition
# File lib/striuct/instancemethods/validation.rb, line 46 def strict? each_pair.all? { |autonym, value| sufficient?(autonym, value) } end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @param value - if no argument and use current assigned value true if passed under any condition
# File lib/striuct/instancemethods/validation.rb, line 39 def sufficient?(key, value=self[key]) accept?(key, value) end
@param [Boolean] include_no_assign @return [Hash]
# File lib/striuct/instancemethods/cast.rb, line 19 def to_h(include_no_assign: true) return @db.dup unless include_no_assign each_pair.to_a.to_h end
@return [String]
# File lib/striuct/instancemethods/to_s.rb, line 32 def to_s (+"#<struct' #{self.class}").tap { |s| each_pair do |autonym, value| s << " #{autonym}=#{value.inspect}," end s.chop! s << '>' } end
@return [self]
# File lib/striuct/instancemethods/cast.rb, line 8 def to_striuct self end
@return [Struct]
# File lib/striuct/instancemethods/cast.rb, line 13 def to_struct self.class.to_struct_class.new(*values) end
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return value / nil - value assigned under the key
# File lib/striuct/instancemethods/assign.rb, line 16 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
@return [Array]
# File lib/striuct/instancemethods/cast.rb, line 26 def values each_value.to_a end
@param [Integer, to_int, Range] keys @return [Array]
# File lib/striuct/instancemethods/values.rb, line 9 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
Protected Instance Methods
# File lib/striuct/instancemethods/compare.rb, line 26 def _db @db end
@param [Symbol] autonym - MUST already converted to native autonym
# File lib/striuct/instancemethods/getter.rb, line 36 def _get(autonym) value = @db[autonym] if with_safety_getter?(autonym) && !accept?(autonym, value) raise InvalidReadingError, "#{value.inspect} is deficient for #{autonym} in #{self.class}" end value end
Private Instance Methods
# File lib/striuct/instancemethods/delegate_class_methods.rb, line 33 def _autonyms self.class.__send__(:_autonyms) end
# File lib/striuct/instancemethods/object.rb, line 52 def _check_frozen raise "can't modify frozen #{self.class}" if frozen? end
# File lib/striuct/instancemethods/object.rb, line 56 def _check_locked(key) raise "can't modify locked member `#{key}`" if locked?(key) end
# File lib/striuct/instancemethods/object.rb, line 60 def _check_must(key) if must?(key) && !assigned?(key) raise InvalidOperationError, "`#{key}` require a value under `must` option" end end
# File lib/striuct/instancemethods/object.rb, line 48 def _initialize_database @db, @locks = {}, {} end
@param [Symbol] autonym - MUST already converted to native autonym @return value
# File lib/striuct/instancemethods/setter.rb, line 26 def _set(autonym, value) _check_frozen _check_locked(autonym) if with_adjuster?(autonym) begin value = instance_exec(value, &adjuster_for(autonym)) rescue Exception raise InvalidAdjustingError end end if with_safety_setter?(autonym) && !accept?(autonym, value) raise InvalidWritingError, "#{value.inspect} is deficient for #{autonym} in #{self.class}" end @db[autonym] = value rescue InvalidValueError unless /in \[\]=/.match?(caller(2..2).first.slice(/([^:]+)\z/)) $!.backtrace.delete_if { |s| /#{Regexp.escape(File.dirname(__FILE__))}/ =~ s } $!.backtrace.first.sub!(/([^:]+)\z/) { "in `#{autonym}='" } end raise end
@param [Symbol] target_autonyms - MUST already converted to native autonym @return [self]
# File lib/striuct/instancemethods/default.rb, line 18 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
# File lib/striuct/instancemethods/object.rb, line 44 def initialize_copy(original) @db, @locks = @db.dup, {} end
# File lib/striuct/instancemethods/object.rb, line 27 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
@param [Symbol, String, to_sym, Integer, to_int] key - name / index @return [self]
# File lib/striuct/instancemethods/lock.rb, line 38 def unlock(key) _check_frozen @locks.delete(autonym_for_key(key)) self end
@return [self]
# File lib/striuct/instancemethods/lock.rb, line 46 def unlock_all _check_frozen @locks.clear self end