Module: ValueSemantics::InstanceMethods
- Defined in:
- lib/value_semantics/instance_methods.rb
Overview
All the instance methods available on ValueSemantics objects
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Loose equality.
-
#[](attr_name) ⇒ Object
Returns the value for the given attribute name.
- #deconstruct_keys(_) ⇒ Object
-
#eql?(other) ⇒ Boolean
Strict equality.
-
#hash ⇒ Object
Unique-ish integer, based on attributes and class of the object.
-
#initialize(attributes = nil) ⇒ Object
Creates a value object based on a hash of attributes.
- #inspect ⇒ Object
- #pretty_print(pp) ⇒ Object
-
#to_h ⇒ Hash
All of the attributes.
-
#with(new_attrs) ⇒ Object
Creates a copy of this object, with the given attributes changed (non-destructive update).
Instance Method Details
#==(other) ⇒ Boolean
Loose equality
127 128 129 |
# File 'lib/value_semantics/instance_methods.rb', line 127 def ==(other) (other.is_a?(self.class) || is_a?(other.class)) && other.to_h.eql?(to_h) end |
#[](attr_name) ⇒ Object
Returns the value for the given attribute name
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/value_semantics/instance_methods.rb', line 90 def [](attr_name) attr = self.class.value_semantics.attributes.find do |attr| attr.name.equal?(attr_name) end if attr public_send(attr_name) else raise UnrecognizedAttributes, "`#{self.class}` has no attribute named `#{attr_name.inspect}`" end end |
#deconstruct_keys(_) ⇒ Object
166 167 168 |
# File 'lib/value_semantics/instance_methods.rb', line 166 def deconstruct_keys(_) to_h end |
#eql?(other) ⇒ Boolean
Strict equality
137 138 139 |
# File 'lib/value_semantics/instance_methods.rb', line 137 def eql?(other) other.class.equal?(self.class) && other.to_h.eql?(to_h) end |
#hash ⇒ Object
Unique-ish integer, based on attributes and class of the object
144 145 146 |
# File 'lib/value_semantics/instance_methods.rb', line 144 def hash to_h.hash ^ self.class.hash end |
#initialize(attributes = nil) ⇒ Object
Creates a value object based on a hash of attributes
19 20 21 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 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/value_semantics/instance_methods.rb', line 19 def initialize(attributes = nil) attributes_hash = if attributes.respond_to?(:to_h) attributes.to_h else raise TypeError, <<-END_MESSAGE.strip.gsub(/\s+/, ' ') Can not initialize a `#{self.class}` with a `#{attributes.class}` object. This argument is typically a `Hash` of attributes, but can be any object that responds to `#to_h`. END_MESSAGE end remaining_attrs = attributes_hash.keys missing_attrs = nil invalid_attrs = nil self.class.value_semantics.attributes.each do |attr| if remaining_attrs.delete(attr.name) value = attributes_hash.fetch(attr.name) elsif attr.optional? value = attr.default_generator.() else missing_attrs ||= [] missing_attrs << attr.name next end coerced_value = attr.coerce(value, self.class) if attr.validate?(coerced_value) instance_variable_set(attr.instance_variable, coerced_value) else invalid_attrs ||= {} invalid_attrs[attr.name] = coerced_value end end # TODO: aggregate all exceptions raised from #initialize into one big # exception that explains everything that went wrong, instead of multiple # smaller exceptions. Unfortunately, this would not be backwards # compatible. unless remaining_attrs.empty? raise UnrecognizedAttributes.new( "`#{self.class}` does not define attributes: " + remaining_attrs.map { |k| '`' + k.inspect + '`' }.join(', ') ) end if missing_attrs raise MissingAttributes.new( "Some attributes required by `#{self.class}` are missing: " + missing_attrs.map { |a| "`#{a}`" }.join(', ') ) end if invalid_attrs raise InvalidValue.new( "Some attributes of `#{self.class}` are invalid:\n" + invalid_attrs.map { |k,v| " - #{k}: #{v.inspect}" }.join("\n") + "\n" ) end end |
#inspect ⇒ Object
148 149 150 151 152 153 154 |
# File 'lib/value_semantics/instance_methods.rb', line 148 def inspect attrs = to_h .map { |key, value| "#{key}=#{value.inspect}" } .join(" ") "#<#{self.class} #{attrs}>" end |
#pretty_print(pp) ⇒ Object
156 157 158 159 160 161 162 163 164 |
# File 'lib/value_semantics/instance_methods.rb', line 156 def pretty_print(pp) pp.object_group(self) do to_h.each do |attr, value| pp.breakable pp.text("#{attr}=") pp.pp(value) end end end |
#to_h ⇒ Hash
115 116 117 118 119 |
# File 'lib/value_semantics/instance_methods.rb', line 115 def to_h self.class.value_semantics.attributes .map { |attr| [attr.name, __send__(attr.name)] } .to_h end |
#with(new_attrs) ⇒ Object
Creates a copy of this object, with the given attributes changed (non-destructive update)
108 109 110 |
# File 'lib/value_semantics/instance_methods.rb', line 108 def with(new_attrs) self.class.new(to_h.merge(new_attrs)) end |