All calculators in Solidus inherit from the Spree::Calculator base class. They calculate and return the value of promotions, taxes, and shipping charges. Solidus includes built-in calculators for common types of calculations, such as flat rate shipping, percentage discounts, sales tax, and value-added tax (VAT).

Whenever you create a new shipping method, tax rate, or promotion action, you also create a new instance of a Spree::Calculator.

For example, if you create a new shipping method called "USPS Ground" that charges a flat rate of $10 USD, you would be creating an instance of the Spree::Calculator::Shipping::FlatRate calculator:

  • The new calculator instance would have calculable_type of Spree::ShippingMethod. This is because it has a polymorphic relationship with a shipping method, rather than a tax rate or promotion action. See calculables for more information about this relationship.
  • The new calculator instance's preferences attribute would have a value of {:preference=>10, :currency=>"USD"}.


Spree::Calculator objects have the following attributes:

  • type: The type of calculator being used. For example, if the object calculates shipping, it could be any available shipping calculator, such as Spree::Calculator::Shipping::FlatRate.
  • calculable_type and calculable_id: The calculable type and its matching ID. For example, if the object calculates shipping, the calculable would be from the Spree::ShippingMethod model. See calculables for more information.
  • preferences: A hash of the calculator's preferences and the values of those preferences. Each type of calculator has its own preferences. See preferences for more information.


A calculable is an object that needs to be calculated by a Spree::Calculator. In Rails, this is an example of a polymorphic association : all calculators share a common base class, but they can calculate different types of objects.

In the case of Spree::Calculators, there are three different calculable_types:

  • Spree::ShippingMethod
  • Spree::TaxRate
  • Spree::PromotionAction

A calculable includes the Spree::CalculatedAdjustments module. This module requires that each calculable has one calculator object. So, for each calculable object, an instance of a Spree::Calculator should also be created.

For example, a shipping method called "USPS Ground" charges a flat rate of $10 USD. The shipping method is calculable and requires an associated calculator. So, the rate for each shipment is calculated by the associated Spree::Calculator::Shipping::FlatRate object.

Similarly, each tax rate in your store is calculable. So, instance of the Spree::Calculator::DefaultTax calculator is created and calculates the amount of tax that should be applied to line items, shipments, or orders.


Each Spree::Calculator has static model preferences . Each instance of a calculator has a preferences attribute that stores a hash of preferences.

For example, you may have two flat shipping rates configured in your store. If you look up each of your Spree::Calculator::Shipping::FlatRate calculators, you can see how the static preferences have different settings:

# => {:amount=>8, :currency=>"USD"}

# => {:amount=>4, :currency=>"EUR"}


Because each type of calculator has different functionality, each calculator has its own set of preferences.

For example, a calculator that uses a percentage for calculations would not have a :currency preference, but any calculator that uses a specific amount of currency would have a :currency preference::

# => {:amount=>4, :currency=>"EUR"}

# => {:flat_percent=>0.2e1}


Preferred methods

For each preference on a calculator, you can use a preferred_<preference> method to get or set the value of the preference (where <preference> is the name of the preference). For example

      Spree::Calculator.find(1).update(preferred_amount: 20)


Custom calculators

If Solidus's built-in calculators are not sufficient for your store, you can create your own custom calculators. Because promotion, shipping, and tax calculators have different requirements, we have an article describing each type of custom calculator you may want to build:


Solidus is an open source platform supported by the community. We encourage everyone using Solidus to contribute back to the documentation and the code.

If you’re interested in contributing to the docs, get started with the contributing guidelines. If you see something that needs fixing and can’t do it yourself, please send us an email.