Class: ContractValueObject
- Inherits:
-
Object
- Object
- ContractValueObject
- Includes:
- Contracts
- Defined in:
- lib/contract_value_object.rb,
lib/contract_value_object/version.rb,
lib/contract_value_object/error_formatter.rb,
lib/contract_value_object/definition_error.rb
Defined Under Namespace
Classes: DefinitionError, ErrorFormatter
Constant Summary collapse
- VERSION =
'0.1.0'
Class Attribute Summary collapse
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
-
#hash ⇒ Object
treating contract value objects with the same values as the same object for hashes and sets.
-
#initialize(**attributes) ⇒ ContractValueObject
constructor
A new instance of ContractValueObject.
- #inspect ⇒ Object
- #to_h ⇒ Object
Constructor Details
#initialize(**attributes) ⇒ ContractValueObject
Returns a new instance of ContractValueObject.
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/contract_value_object.rb', line 50 def initialize(**attributes) error_presenter = self.class.error_presenter class_attributes = self.class.attributes defaults = self.class.defaults = DefinitionError::ErrorMessage # determine attributes that were not passed in but should have been missing_attributes = class_attributes.keys - attributes.keys - defaults.keys missing_attribute_errors = missing_attributes.flat_map do |attribute| next([]) if class_attributes[attribute].is_a?(Contracts::Optional) .new(attribute, error_presenter.missing(attribute, class_attributes.fetch(attribute))) end # determine extraneous attributes that should not have been passed in unexpected_attributes = attributes.keys - class_attributes.keys unexpected_attribute_errors = unexpected_attributes.map do |attribute| .new(attribute, error_presenter.unexpected(attribute)) end # set attributes on the object and raise if they do not obey the contract setter_errors = defaults.merge(attributes).flat_map do |attribute, value| next([]) if unexpected_attributes.include?(attribute) begin contract = class_attributes.fetch(attribute) contract.within_opt_hash! if contract.is_a?(Contracts::Optional) # begin support customized setter send("#{attribute}=", value) set_value = instance_variable_get("@#{attribute}") # end support for customized setter if Contract.valid?(set_value, contract) [] else raise ArgumentError, error_presenter.contract_failure(attribute, set_value, contract) end rescue self.class::DefinitionError => error .new(attribute, error..gsub("\n", "\n\t")) rescue StandardError => error .new(attribute, error.) end end errors = missing_attribute_errors + unexpected_attribute_errors + setter_errors return if errors.empty? raise DefinitionError, errors end |
Class Attribute Details
.error_presenter ⇒ Object
44 45 46 |
# File 'lib/contract_value_object.rb', line 44 def error_presenter @error_presenter ||= self::ErrorFormatter.new end |
Class Method Details
.attributes(attributes = nil) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/contract_value_object.rb', line 11 def attributes(attributes = nil) if attributes.nil? return @attributes if instance_variable_defined?(:@attributes) raise ArgumentError, 'Calling for attributes without having defined them.' end attr_accessor(*attributes.keys) attr_writers = attributes.keys.map { |attribute| :"#{attribute}=" } private *attr_writers @attributes = attributes end |
.defaults(defaults = nil) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/contract_value_object.rb', line 25 def defaults(defaults = nil) return @defaults ||= {} if defaults.nil? unexpected_defaults = defaults.keys - attributes.keys unless unexpected_defaults.empty? raise ArgumentError, "Unexpected defaults are set: #{unexpected_defaults.map(&:to_s).join(', ')}" end non_optional = defaults.select do |attribute, _| !attributes.fetch(attribute).is_a?(Contracts::Optional) end raise ArgumentError, "Unexpected non-optional defaults: #{non_optional.keys.join(', ')}" unless non_optional.empty? @defaults = defaults end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
111 112 113 114 115 116 117 |
# File 'lib/contract_value_object.rb', line 111 def ==(other) return super(other) unless self.class == other.class self.class.attributes.all? do |attribute, _type| public_send(attribute) == other.public_send(attribute) end end |
#hash ⇒ Object
treating contract value objects with the same values as the same object for hashes and sets
107 108 109 |
# File 'lib/contract_value_object.rb', line 107 def hash to_h.hash end |
#inspect ⇒ Object
121 122 123 |
# File 'lib/contract_value_object.rb', line 121 def inspect "#{self.class} #{to_h.inspect}" end |
#to_h ⇒ Object
98 99 100 101 102 103 104 |
# File 'lib/contract_value_object.rb', line 98 def to_h key_value_pairs = self.class.attributes.map do |attribute, _type| [attribute, public_send(attribute)] end key_value_pairs.to_h end |