Class: Data

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-next/core/data.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**kwargs) ⇒ Data

Returns a new instance of Data.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ruby-next/core/data.rb', line 77

def initialize(**kwargs)
  kwargs_size = kwargs.size
  members_size = members.size

  if kwargs_size > members_size
    extras = kwargs.except(*members).keys

    if extras.size > 1
      raise ArgumentError, "unknown keywords: #{extras.map { ":#{_1}" }.join(", ")}"
    else
      raise ArgumentError, "unknown keyword: :#{extras.first}"
    end
  elsif kwargs_size < members_size
    missing = members.select { |k| !kwargs.include?(k) }

    if missing.size > 1
      raise ArgumentError, "missing keywords: #{missing.map { ":#{_1}" }.join(", ")}"
    else
      raise ArgumentError, "missing keyword: :#{missing.first}"
    end
  end

  @attributes = members.map { |m| [m, kwargs[m]] }.to_h
end

Class Attribute Details

.membersObject (readonly)

Returns the value of attribute members.



19
20
21
# File 'lib/ruby-next/core/data.rb', line 19

def members
  @members
end

Class Method Details

.define(*args, &block) ⇒ Object

Raises:

  • (ArgumentError)


22
23
24
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/ruby-next/core/data.rb', line 22

def self.define(*args, &block)
  raise ArgumentError if args.any?(/=/)
  if block
    mod = Module.new
    mod.define_singleton_method(:_) do |klass|
      klass.class_eval(&block)
    end
    arity_converter = mod.method(:_)
  end
  klass = ::Class.new(self)

  klass.instance_variable_set(:@members, args.map(&:to_sym).freeze)

  klass.define_singleton_method(:new) do |*new_args, **new_kwargs, &block|
    init_kwargs = if new_args.any?
      raise ArgumentError, "unknown arguments #{new_args[members.size..].join(", ")}" if new_args.size > members.size
      members.take(new_args.size).zip(new_args).to_h
    else
      new_kwargs
    end

    allocate.tap do |instance|
      instance.send(:initialize, **init_kwargs, &block)
    end.freeze
  end

  class << klass
    alias_method :[], :new
    undef_method :define
  end

  args.each do |arg|
    if klass.method_defined?(arg)
      raise ArgumentError, "duplicate member #{arg}"
    end
    klass.define_method(arg) do
      @attributes[arg]
    end
  end

  if arity_converter
    klass.class_eval(&arity_converter)
  end

  klass
end

.inherited(subclass) ⇒ Object



69
70
71
# File 'lib/ruby-next/core/data.rb', line 69

def self.inherited(subclass)
  subclass.instance_variable_set(:@members, members)
end

Instance Method Details

#==(other) ⇒ Object



125
126
127
# File 'lib/ruby-next/core/data.rb', line 125

def ==(other)
  self.class == other.class && to_h == other.to_h
end

#deconstructObject



102
103
104
# File 'lib/ruby-next/core/data.rb', line 102

def deconstruct
  @attributes.values
end

#deconstruct_keys(array) ⇒ Object

Raises:

  • (TypeError)


106
107
108
109
110
111
# File 'lib/ruby-next/core/data.rb', line 106

def deconstruct_keys(array)
  raise TypeError unless array.is_a?(Array) || array.nil?
  return @attributes if array&.first.nil?

  @attributes.slice(*array)
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


121
122
123
# File 'lib/ruby-next/core/data.rb', line 121

def eql?(other)
  self.class == other.class && hash == other.hash
end

#hashObject



117
118
119
# File 'lib/ruby-next/core/data.rb', line 117

def hash
  to_h.hash
end

#inspectObject Also known as: to_s



129
130
131
132
133
134
135
136
137
138
# File 'lib/ruby-next/core/data.rb', line 129

def inspect
  attribute_markers = @attributes.map do |key, value|
    insect_key = key.to_s.start_with?("@") ? ":#{key}" : key
    "#{insect_key}=#{value}"
  end.join(", ")

  display = ["data", self.class.name, attribute_markers].compact.join(" ")

  "#<#{display}>"
end

#membersObject



73
74
75
# File 'lib/ruby-next/core/data.rb', line 73

def members
  self.class.members
end

#to_h(&block) ⇒ Object



113
114
115
# File 'lib/ruby-next/core/data.rb', line 113

def to_h(&block)
  @attributes.to_h(&block)
end

#with(**kwargs) ⇒ Object



141
142
143
144
145
# File 'lib/ruby-next/core/data.rb', line 141

def with(**kwargs)
  return self if kwargs.empty?

  self.class.new(**@attributes.merge(kwargs))
end