Class: WhittakerTech::Midas::Coin::Allocation
- Inherits:
-
Object
- Object
- WhittakerTech::Midas::Coin::Allocation
- Defined in:
- app/models/whittaker_tech/midas/coin/allocation.rb
Overview
Allocation represents a per-unit interpretation of a Coin.
Conceptual model
Coin -> canonical, payable money (what exists)
Allocation -> "this Coin, spread across N units, using policy X"
An Allocation answers two questions:
- What does one unit cost? —
#value - What does a given quantity cost? —
#price
Immutability
Allocation is:
- immutable —
@coin,@divisor, and@rounding_policyare frozen on construction and never mutated. - not persisted — Allocation is a pure value object.
- minor-unit safe — it never stores sub-minor-unit amounts; rounding is applied before returning a Coin.
See also: Coin#allocate
Instance Attribute Summary collapse
-
#coin ⇒ Coin
readonly
The total monetary amount this Allocation is based on.
-
#divisor ⇒ Numeric
(also: #per)
readonly
The number of units the coin covers (the divisor).
-
#rounding_policy ⇒ Symbol
readonly
The rounding policy applied to per-unit calculations.
Instance Method Summary collapse
-
#initialize(coin:, divisor:, rounding_policy:) ⇒ Allocation
constructor
A new instance of Allocation.
-
#inspect ⇒ String
Human-readable representation for logs and console output.
-
#price(qty: 1) ⇒ Coin
Returns the total price for a given quantity of units.
-
#value ⇒ Coin
Returns the per-unit Coin after dividing by
#divisorand applying the#rounding_policy.
Constructor Details
#initialize(coin:, divisor:, rounding_policy:) ⇒ Allocation
Returns a new instance of Allocation.
64 65 66 67 68 69 70 71 72 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 64 def initialize(coin:, divisor:, rounding_policy:) raise TypeError unless coin.is_a?(WhittakerTech::Midas::Coin) raise TypeError unless divisor.is_a?(Numeric) && divisor.positive? raise ArgumentError unless WhittakerTech::Midas::ROUNDING_POLICIES.key?(rounding_policy) @coin = coin.freeze @divisor = divisor @rounding_policy = rounding_policy.freeze end |
Instance Attribute Details
#coin ⇒ Coin (readonly)
Returns the total monetary amount this Allocation is based on.
36 37 38 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 36 def coin @coin end |
#divisor ⇒ Numeric (readonly) Also known as: per
Returns the number of units the coin covers (the divisor).
39 40 41 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 39 def divisor @divisor end |
#rounding_policy ⇒ Symbol (readonly)
Returns the rounding policy applied to per-unit calculations.
42 43 44 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 42 def rounding_policy @rounding_policy end |
Instance Method Details
#inspect ⇒ String
Human-readable representation for logs and console output.
108 109 110 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 108 def inspect "#<#{self.class.name} coin=#{coin.inspect} divisor=#{divisor} rounding_policy=#{rounding_policy}>" end |
#price(qty: 1) ⇒ Coin
Returns the total price for a given quantity of units.
Uses (total_minor * qty) / divisor rounded via #rounding_policy.
Equivalent to qty units at the per-unit rate, but computed from the
original total to minimise accumulated rounding error.
97 98 99 100 101 102 103 104 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 97 def price(qty: 1) raise ArgumentError unless qty.is_a?(Numeric) && qty >= 0 WhittakerTech::Midas::Coin.value( round((coin.currency_minor * qty) / divisor), coin.currency_code ).freeze end |
#value ⇒ Coin
Returns the per-unit Coin after dividing by #divisor and applying the
#rounding_policy.
The result is still a Coin — payable money representing a single unit.
80 81 82 |
# File 'app/models/whittaker_tech/midas/coin/allocation.rb', line 80 def value coin.divide(divisor, rounding_policy: rounding_policy) end |