Class: Value

Inherits:
Struct
  • Object
show all
Defined in:
lib/value.rb

Overview

‘Value` generates `Struct` classes with safer constructors. It is designed to provide a superset of the interface of the `Values` gem, with better performance, by subclassing actual native Structs.

‘Value` constructors require all mandatory arguments to be provided, and supply default values for all optional arguments. Additionally, the resulting instance is frozen. To obtain a mutable Value, `dup` the result.

‘Value` structure classes are created similarly to `Struct`s, with the addition that optional arguments are may be specified as keyword arguments: `ValueType = Value.new(:a, :b, c: default_value)`. The default values to optional arguments are saved at class creation time and supplied as default constructor arguments to instances. Default values are aliased, so providing mutable defaults is discouraged.

Two instance constructors are provided, with positional and keyword arguments.

Value types may be constructed with positional arguments using ‘new`. Arguments are provided in the same order as specified at class initialization time, with mandatory arguments before optional ones. For example: `ValueType.new(1, 2)`, `ValueType.new(1, 2, 3)`

Value types may be constructed with keyword arguments using ‘with`. For example: `ValueType.with(a: 1, b: 2, c: 3)`

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(*required_args, **optional_args, &block) ⇒ Object



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
# File 'lib/value.rb', line 29

def new(*required_args, **optional_args, &block)
  arguments = {}
  required_args.each { |arg| arguments[arg] = true }
  optional_args.each_key { |arg| arguments[arg] = false }
  validate_names(*arguments.keys)

  clazz = super(*arguments.keys, &nil)

  # define class and instance methods in modules so that the class can
  # override them
  keyword_constructor = generate_keyword_constructor(arguments)
  class_method_module = Module.new do
    module_eval(keyword_constructor)
    define_method(:__constructor_default) do |name|
      optional_args.fetch(name)
    end
  end
  clazz.extend(class_method_module)

  constructor = generate_constructor(arguments)
  instance_method_module = Module.new do
    module_eval(constructor)
  end
  clazz.include(instance_method_module)

  # Evaluate the block in the context of the class
  clazz.class_eval(&block) if block_given?

  clazz
end

Instance Method Details

#with(hash = {}) ⇒ Object



123
124
125
126
# File 'lib/value.rb', line 123

def with(hash = {})
  return self if hash.empty?
  self.class.with(to_h.merge(hash))
end