CommerceUnits

Another units library for Ruby which helps with maintaining consist mathematics. But unlike scientific (SI) units, where we're all agreed to things like 1000g = 1kg, 1 hour = 60 minutes, and whatnot, commerce_units makes no assumptions on what kinds of units there.

Instead, commerical units allows you to define your own conversion rates between different units and operations such as multiply and divide will automatically handle conversions and reductions while addition and subtraction will throw errors if inappropriately dimensioned values are added together.

Installation

Add this line to your application's Gemfile:

gem 'commerce_units'

And then execute:

$ bundle

Or install it yourself as:

$ gem install commerce_units

Usage

Step 1: generate the migration to create the dimensions

rails generate commerce_units

What?! This is unit library, yet you demand a database migration? What sort of stupid shit...

Well, the justification is that this is a commerce units library, and, in business, I have no idea what sort of units you might be using to quantify your transactions. In my case, I built this library originally to use for money per weight, and the dimension of money has all sorts of units (dollars, cents, rupies, RMB, yen, pound-sterling, etc.) which even change with time.

If you think your business is measured in dollars per boxes, then it's up to you to declare dollars with a money dimension and boxes in some other root dimension.

Step 2: seed the CommerceUnits::Dimension record with the units you'll need

Declare your units, here's an example

CommerceUnits::Dimension.create! root_dimension: :money,
  unit_name: "dollar",
  multiply_constant: 1.0,
  unitary_role: :primary

CommerceUnits::Dimension.create! root_dimension: :money,
  unit_name: "cent",
  multiply_constant: 100.0 # 100 cents go into 1 us dollar

CommerceUnits::Dimension.create! root_dimension: :money,
  unit_name: "RMB",
  multiply_constant: 6.654 # 6.654 RMB go into 1 us dollar

CommerceUnits::Dimension.create! root_dimension: :money,
  unit_name: "euro",
  multiply_constant: 12000 # 12000 euros go into 1 us dollar because Yuropoor is poor

CommerceUnits::Dimension.create! root_dimension: :mass,
  unit_name: 'pound',
  multiply_constant: 1.0,
  unitary_role: :primary

CommerceUnits::Dimension.create! root_dimension: :mass,
  unit_name: 'ton',
  multiply_constant: 2000 # 2000 pounds go into 1 ton

CommerceUnits::Dimension.create! root_dimension: :mass,
  unit_name: 'landwhale',
  multiply_constant: 354 # 354 pounds go into 1 landwhale

Step 3: Use

Here's an example

dollar_per_pound = CommerceUnit::Value.from_params number: 1234, units: "dollar / pound"
dollar_per_pound.to_s # 1234 dollar / pound

euro_per_ton = CommerceUnit::Value.from_params number: 34, units: "euro / ton"
dollar_per_pound + euro_per_ton # 1234.00000... dollar / pound

dollar_per_landwhale_squared = CommerceUnit::Value.from_params number: 1, units: "dollar / landwhale / landwhale"
euro_per_ton + dollar_per_landwhale_squared # throws unit mismatch error

(euro_per_ton / dollar_per_pound ).unitless? # true

Assumptions

If "mango" and "chair" are both declared as commerce units of the same dimension, then any amount of mangos can be converted to chairs by a constant multiplication. This necessarily means 0 mangos == 0 chairs

If you specify 0 as the multiply_constant, you'll eat a face full of DivideByZero errors.

Contributing

  1. Fork it ( http://github.com//commerce_units/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request