class Redmine::Value

Base class for immutable value objects.

Value objects with the same attributes are considered equal. Value objects cannot be modified, but new values can be constructed by applying new attribute values to existing values.

Attributes

hash[R]

Public Class Methods

attribute(name, type: nil, path: nil) click to toggle source

Define a new attribute for this value. Attributes can be casted into a specific type, and can optionally be read from a path inside a nested structure (see Rubys ‘dig` method).

@param [Symbol, to_sym] name @param [Class, parse] type conversion method or class that can be

used to parse the incoming values.

@param [Array] path for ‘dig` to retrieve nested values @return [nil]

# File lib/redmine/value.rb, line 38
def self.attribute(name, type: nil, path: nil)
  attributes << name.to_sym
  attr_reader name

  define_method :"#{name}=" do |value|
    value = value.dig(*Array(path)) if path && value.respond_to?(:dig)
    parsed_value = self.class.parse_value(value, type)
    instance_variable_set(:"@#{name}", parsed_value)
  end

  private :"#{name}="
  nil
end
attributes() click to toggle source

List of all known attributes supported by this Value.

# File lib/redmine/value.rb, line 11
def self.attributes
  @attributes ||= []
end
new(attrs = {}) click to toggle source

@param [Hash] attrs

# File lib/redmine/value.rb, line 53
def initialize(attrs = {})
  attrs.to_h.each do |name, value|
    send(:"#{name}=", value)
  end
  @hash = self.class.hash ^ to_a.hash
  freeze
end
parse_value(value, type = nil) click to toggle source

@param [Object] value raw data to be tranformed into ‘type`. @param [Object, parse] type @return [Object] value parsed to `type`

# File lib/redmine/value.rb, line 18
def self.parse_value(value, type = nil)
  case type
  when ->(t) { t.nil? } then value
  when ->(t) { t === value } then value
  when ->(t) { t.respond_to?(:parse) } then type.parse(value)
  when ->(t) { Kernel.respond_to?(t.to_s) }
    Kernel.send(type.to_s, value)
  else raise ArgumentError, "Invalid type #{type.inspect}"
  end
end

Public Instance Methods

==(other)
Alias for: eql?
eql?(other) click to toggle source

@return [Bool]

# File lib/redmine/value.rb, line 73
def eql?(other)
  hash == other.hash
end
Also aliased as: ==
to_a() click to toggle source

@return [Array]

# File lib/redmine/value.rb, line 84
def to_a
  self.class.attributes.map { |attr| [attr, send(attr)] }
end
to_h() click to toggle source

@return [Hash]

# File lib/redmine/value.rb, line 79
def to_h
  Hash[to_a]
end
with(attrs = {}) click to toggle source

Create a new value based on the current value, but with the incoming attributes assigned. This “changes” the value, but leaves the original value intact – as you’ll get a new instance instead.

@param [Hash] attrs new attributes to be merged with this value’s

attributes.

@return [Value]

# File lib/redmine/value.rb, line 68
def with(attrs = {})
  self.class.new(to_h.merge(attrs))
end