Module: Value

Defined in:
lib/value-1.0.rb,
lib/value-1.0/version.rb

Overview

Represents an immutable [value object](en.wikipedia.org/wiki/Value_object) with an #initialize method, equality checks #== and #eql?, a #hash function, and an #inspect method.

Examples:

A Point Value Object

class Point
  Value :x, :y
end

A Point Value Object with Public Accessors

class Point
  Value :x, :y
  public(*attributes)
end

A Value Object with Optional Attributes

class Money
  Value :amount, [:currency, :USD]
end

A Value Object with a Comparable Attribute

class Vector
  Value :a, :b, :comparable => :a
end

Defined Under Namespace

Modules: Comparable Classes: Attributes

Constant Summary collapse

Version =
Inventory.new(1, 1, 3){
  authors{
    author 'Nikolai Weibull', '[email protected]'
  }

  homepage 'http://disu.se/software/value'

  licenses{
    license 'LGPLv3+',
            'GNU Lesser General Public License, version 3 or later',
            'http://www.gnu.org/licenses/'
  }

  def dependencies
    super + Inventory::Dependencies.new{
      development 'inventory-rake', 1, 6, 0
      development 'inventory-rake-tasks-yard', 1, 4, 0
      development 'lookout', 3, 0, 0
      development 'lookout-rake', 3, 1, 0
      development 'yard', 0, 8, 0
      development 'yard-heuristics', 1, 2, 0
    }
  end

  def package_libs
    %w[attributes.rb
       comparable.rb]
  end
}

Instance Method Summary collapse

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Returns True if the receiver’s class and all of its Attributes ‘#==` those of OTHER.

Returns:

  • (Boolean)

    True if the receiver’s class and all of its Attributes ‘#==` those of OTHER



69
70
71
# File 'lib/value-1.0.rb', line 69

def ==(other)
  self.class == other.class and attributes.all?{ |e| send(e) == other.send(e) }
end

#hashFixnum

Returns The hash value of the receiver’s class XORed with the hash value of the Array of the values of the Attributes of the receiver.

Returns:

  • (Fixnum)

    The hash value of the receiver’s class XORed with the hash value of the Array of the values of the Attributes of the receiver



78
79
80
# File 'lib/value-1.0.rb', line 78

def hash
  self.class.hash ^ attributes.map{ |e| send(e) }.hash
end

#initialize(*arguments) {|?| ... } ⇒ Object

Creates a new value object, using ARGUMENTS to set up the value’s required, optional, and splat attributes, and the given block, if given, if a block is desired.

Parameters:

  • arguments (Object, )

Yields:

  • (?)

Raises:

  • (ArgumentError)

    If ARGUMENTS#length is less than the number of required attributes

  • (ArgumentError)

    If ARGUMENTS#length is greater than the number of required and optional attributes



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

def initialize(*arguments)
  raise ArgumentError,
    'wrong number of arguments (%d for %d)' %
      [arguments.length, attributes.required.length] if
        arguments.length < attributes.required.length
  raise ArgumentError,
    'wrong number of arguments (%d for %d)' %
      [arguments.length,
       attributes.required.length + attributes.optional.length] if
        arguments.length > attributes.required.length +
          attributes.optional.length and not attributes.splat
  instance_variable_set :"@#{attributes.block}",
    block_given? ? Proc.new : nil if attributes.block
  instance_variable_set :"@#{attributes.splat}",
    arguments[attributes.required.length +
              attributes.optional.length..-1] if attributes.splat
  attributes.required.each_with_index do |value, index|
    instance_variable_set :"@#{value}", arguments[index]
  end
  attributes.optional.each_with_index do |(value, default), index|
    offset = attributes.required.length + index
    instance_variable_set :"@#{value}",
      offset >= arguments.length ? default : arguments[offset]
  end
end

#inspectString

Returns The inspection of the receiver.

Returns:

  • (String)

    The inspection of the receiver



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/value-1.0.rb', line 83

def inspect
  '%s.new(%s)' %
    [self.class,
     [attributes.required.map{ |name| send(name).inspect },
      attributes.optional.
        map{ |name, default| [send(name), default] }.
        select{ |value, default| value != default or attributes.splat }.
        map{ |value, _| value },
      attributes.splat ? send(attributes.splat).map{ |value| value.inspect } : [],
      attributes.block ? ['&%s' % [send(attributes.block).inspect]] : []].
        flatten.join(', ')]
end