class Data
Private Class Methods
define(*members, &block)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 30 def self.define(*members, &block) members.each do |m| raise TypeError, "#{m} is not a Symbol" unless m.is_a?(Symbol) || m.is_a?(String) raise ArgumentError, "invalid data member: #{m}" if m.end_with?("=") end members = members.map(&:to_sym) raise ArgumentError, "duplicate members" if members.uniq! klass = instance_eval <<-"end_define", __FILE__, __LINE__ + 1 Class.new(::Backports::Data) do # Class.new(::Data) do def self.members # def self.members #{members.inspect} # [:a_member, :another_member] end # end end # end end_define members.each do |m| klass.define_method(m) { @__members__[m]} end class << klass def new(*values, **named_values) if named_values.empty? if values.size > members.size raise ArgumentError, "wrong number of arguments (given #{values.size}, expected 0..#{members.size})" end super(**members.first(values.size).zip(values).to_h) else unless values.empty? raise ArgumentError, "wrong number of arguments (given #{values.size}, expected 0)" end super(**named_values) end end undef :define end klass.class_eval(&block) if block klass end
new(**named_values)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 88 def initialize(**named_values) given = named_values.keys missing = members - given unless missing.empty? missing = missing.map(&:inspect).join(", ") raise ArgumentError, "missing keywords: #{missing}" end if members.size < given.size extra = (given - members).map(&:inspect).join(", ") raise ArgumentError, "unknown keywords: #{extra}" end @__members__ = named_values.freeze freeze end
Private Instance Methods
==(other)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 78 def ==(other) return false unless other.instance_of?(self.class) @__members__ == other.to_h end
deconstruct()
click to toggle source
# File lib/backports/3.2.0/data.rb, line 19 def deconstruct @__members__.values end
deconstruct_keys(keys_or_nil)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 23 def deconstruct_keys(keys_or_nil) return @__members__ unless keys_or_nil raise TypeError, "Expected symbols" unless keys_or_nil.is_a?(Array) && keys_or_nil.all? {|s| s.is_a?(Symbol)} @__members__.slice(*keys_or_nil) end
eql?(other)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 72 def eql?(other) return false unless other.instance_of?(self.class) @__members__.eql?(other.to_h) end
hash()
click to toggle source
# File lib/backports/3.2.0/data.rb, line 84 def hash @__members__.hash end
initialize_copy(other)
click to toggle source
Why is ‘initialize_copy` specialized in MRI and not just `initialize_dup`? Let’s follow the pattern anyways
# File lib/backports/3.2.0/data.rb, line 105 def initialize_copy(other) @__members__ = other.to_h freeze end
inspect()
click to toggle source
# File lib/backports/3.2.0/data.rb, line 110 def inspect data = @__members__.map {|k, v| "#{k}=#{v.inspect}"}.join(", ") space = data != "" && self.class.name ? " " : "" "#<data #{self.class.name}#{space}#{data}>" end
marshal_dump()
click to toggle source
# File lib/backports/3.2.0/data.rb, line 116 def marshal_dump @__members__ end
marshal_load(members)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 120 def marshal_load(members) @__members__ = members freeze end
members()
click to toggle source
class method defined in ‘define`
# File lib/backports/3.2.0/data.rb, line 126 def members self.class.members end
to_h(&block)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 134 def to_h(&block) @__members__.to_h(&block) end
with(**update)
click to toggle source
# File lib/backports/3.2.0/data.rb, line 138 def with(**update) return self if update.empty? self.class.new(**@__members__.merge(update)) end