Module: Plutonium::Models::HasCents

Extended by:
ActiveSupport::Concern
Included in:
Resource::Record
Defined in:
lib/plutonium/models/has_cents.rb

Overview

Note:

This module automatically handles validation propagation. If a validation error is applied to the cents attribute, the decimal attribute will be marked as invalid.

Note:

The module uses BigDecimal for internal calculations to ensure precision in monetary operations.

HasCents module provides functionality to handle monetary values stored as cents and expose them as decimal values. It also ensures that validations applied to the cents attribute are inherited by the decimal attribute.

Examples:

Usage

class Product < ApplicationRecord
  include Plutonium::Models::HasCents

  has_cents :price_cents
  has_cents :cost_cents, name: :wholesale_price, rate: 1000
  has_cents :quantity_cents, name: :quantity, rate: 1
  has_cents :total_cents, suffix: "value"

  validates :price_cents, numericality: { greater_than_or_equal_to: 0 }
end

Basic Usage

product = Product.new(price: 10.99)

product.price_cents #=> 1099
product.price #=> 10.99

product.wholesale_price = 5.5
product.cost_cents #=> 5500

product.quantity = 3
product.quantity_cents #=> 3

Truncation

product.price = 10.991
product.price_cents #=> 1099

product.price = 10.995
product.price_cents #=> 1099

product.price = 10.999
product.price_cents #=> 1099

product.total_value = 100.50
product.total_cents #=> 10050

Validation Inheritance

product = Product.new(price: -10.99)
product.valid? #=> false
product.errors[:price_cents] #=> ["must be greater than or equal to 0"]
product.errors[:price] #=> ["is invalid"]

Reflection

Product.has_cents_attributes
#=> {
#     price_cents: { name: :price, rate: 100 },
#     cost_cents: { name: :wholesale_price, rate: 1000 },
#     quantity_cents: { name: :quantity, rate: 1 },
#     total_cents: { name: :total_value, rate: 100 }
#   }

Product.has_cents_attribute?(:price_cents) #=> true
Product.has_cents_attribute?(:name) #=> false
Product.has_cents_attributes[:cost_cents] #=> {name: :wholesale_price, rate: 1000}

See Also:

Defined Under Namespace

Modules: ClassMethods

Instance Method Summary collapse

Instance Method Details

#has_cents_unit_for(decimal_attribute) ⇒ String?

Resolves the currency unit (symbol) configured for a has_cents decimal accessor, e.g. :price for has_cents :price_cents, unit: "£".

Parameters:

  • decimal_attribute (Symbol, String)

    The decimal accessor name.

Returns:

  • (String, nil)

    The unit — a String verbatim, the value of the method named by a Symbol unit (per-row currencies), or nil when the attribute has no unit configured / is not a has_cents accessor.



86
87
88
89
90
91
92
93
94
95
# File 'lib/plutonium/models/has_cents.rb', line 86

def has_cents_unit_for(decimal_attribute)
  decimal_attribute = decimal_attribute.to_sym
  config = self.class.has_cents_attributes.values.find { |opts| opts[:name] == decimal_attribute }
  return unless config

  case (unit = config[:unit])
  when Symbol then public_send(unit)
  else unit
  end
end