Skip to content
Switch branches/tags
Go to file
Cannot retrieve contributors at this time
2852 lines (2212 sloc) 247 KB

Solidus 3.2.0.alpha (master, unreleased)

  • Monkey patch Authentication Bypass by CSRF Weakness vulnerability on solidus_auth_devise for extra security GHSA-5629-8855-gf4g

  • Fix ReDos vulnerability on Spree::EmailValidator::EMAIL_REGEXP GHSA-qxmr-qxh6-2cc9

  • Fix CSRF forgery protection bypass for Spree::OrdersController#populate GHSA-h3fg-h5v3-vf8m

Other important changes

New Solidus applications won't autoload files matching app/**/*_decorator*.rb pattern anymore. For previous Solidus applications, it's something that will keep working as the responsible code was added to your config/application.rb when Solidus was installed. That code is intended to work with Rails' classic autoloader, deprecated on Rails 6 and removed on Rails 7. It keeps working because of a compatibility layer which is also deprecated. However, it may be eventually removed, so you're better off updating your application.rb file. You should substitute:

config.to_prepare do
  Dir.glob(Rails.root.join('app/**/*_decorator*.rb')) do |path|


overrides = "#{Rails.root}/app/overrides" # use your actual directory here
config.to_prepare do
  Dir.glob("#{overrides}/**/*_decorator*.rb").each do |override|
    load override

You may also want to stop using the decorator naming, as it's no longer part of Solidus recommendations (that files are monkey patches; they don't use the decorator pattern). E.g., you can place those files in app/overrides/ and remove the decorator suffix.


Solidus 3.1.5 (v3.1, 2021-12-20)

Solidus 3.1.4 (v3.1, 2021-12-07)

Solidus 3.1.3 (v3.1, 2021-11-17)

  • Monkey patch Authentication Bypass by CSRF Weakness vulnerability on solidus_auth_devise for extra security GHSA-5629-8855-gf4g

Solidus 3.1.1 (v3.1, 2021-09-20)

Solidus 3.1.0 (v3.1, 2021-09-10)

Major changes

Spree.load_defaults: preference defaults depending on the Solidus version

Solidus 3.1 brings a new feature where preference defaults can take different values depending on a specified Solidus version. It makes it possible to stop deprecating old defaults every time we introduce a change in the recommended value for a setting. After all, they're just that; recommendations. Instead, now users can explicitly ask for a given Solidus version defaults and, as before, override the preferences they want.

When upgrading to 3.1, you have to take action to adopt the new behavior. You'll need to add Spree.load_defaults('3.1') on the very top of your spree.rb initializer. As we're not changing any preference default on this release, nothing will break. A warning will be emitted on boot-up until you do it!

However, bumping the version given to load_defaults straight away for future upgrades will not be a safe option. Instead, you'll have to go through the new update process detailed below.

New update process

As aforementioned, preference defaults can change after a Solidus release. Once you have your defaults locked to the current Solidus version, a new upgrade won't break your application because of them. However, it's a good idea to adapt your application to the updated recommended settings. To help with this process, Solidus comes with a generator that you can execute like this:

bin/rails g solidus:update

That generator will create a new initializer called new_solidus_defaults.rb, which will preview all the defaults that have changed between versions, each on a commented line. From that point, you can activate the new defaults one by one and adapt your application incrementally. Once you're done with all of them, you can bump the version given to Spree.load_defaults in the spree.rb initializer and remove the new_solidus_defaults.rb initializer altogether.

You can read in more detail about this process on our guides.

Other important changes

Spree::Price#amount field can no longer be nil. Besides adding the validation at the model layer, we ship with a task that will remove records where the amount is NULL in the database. You should run the task before executing the new migrations:

bin/rails solidus:delete_prices_with_nil_amount
bin/rails railties:install:migrations
bin/rails db:migrate

If you're running migrations automatically on deploy, you should run the task before rolling out the new code. In that case, you first should make sure that you have affected records:

Spree::Price.where(amount: nil).any?

If the above code returns false, you don't need to do anything else. Otherwise, copy the task into your code, and deploy & execute it. Another option is to execute it manually in your console in production. However, be extremely careful when doing that!! ⚠️ ⚠️ ⚠️

Spree::Price.where(amount: nil).delete_all



  • Remove Pending Request Spec: Api Admin update payment state expectations. #4149 (jcowhigjr)
  • Fix gateway_error when no order is defined #4156 (alexblackie)
  • Moving API attribute helpers to API config #4039 (snada)
  • Allow customer returns to reference existing ReturnItems on create through API #4007 (forkata)
  • Let the PriceSelector return a Spree::Price #3925 (swively)



Docs & Guides

Solidus 3.0.5 (v3.0, 2021-12-20)

Solidus 3.0.4 (v3.0, 2021-12-07)

Solidus 3.0.3 (v3.0, 2021-11-17)

  • Monkey patch Authentication Bypass by CSRF Weakness vulnerability on solidus_auth_devise for extra security GHSA-5629-8855-gf4g

Solidus 3.0.2 (v3.0, 2021-09-10)

Solidus 3.0.1 (v3.0, 2021-05-10)

  • Use symbols in polymorphic path for event_links #4048 (tvdeyen)

Solidus 3.0.0 (v3.0, 2021-04-20)

Major Changes

Removal of all code deprecated during the 2.x series

The main change in this major version is the removal of all deprecated code that we introduced during the 2.x series. This means that if any code that was deprecated is still being used, the application will break. Following the deprecation messages in the application logs, it should be quite easy to spot what code needs to be changed.

The main things that could break a Solidus application are:

Paranoia gem has been replaced by Discard gem

All references to methods added to models by Paranoia will raise a NoMethodError exception now. Some of those methods are:

  • paranoia_destroy
  • paranoia_delete
  • with_deleted
  • only_deleted
  • really_destroy!
  • after_real_destroy

Pull Requests:

Removed core support to first_name and last_name in Spree::Address

In Solidus v2.11, we added a name attribute to Spree::Address, which is being populated combining first_name and last_name values every time a new address is added to the system. We also provided a rake tasks to update all existing records in order to get applications ready for Solidus 3.0.

With this major version, name is the only supported attributes. first_name and last_name fields are already in the database so if needed, a store can revert this change implementing their own logic.

See 3234 for the rationale behind this change.

Pull Requests:

All the other deprecations removal

For a complete reference to rest of the code removed, these PRs can be taken as reference:

Removal without deprecations

We also removed some code that didn't need a deprecation warning. Be sure that your codebase doesn't use any of the following:

  • Spree::LineItem::CurrencyMismatch exception: we are not using it anymore since the behavior we had with Spree::Config.raise_with_invalid_currency = true has been removed.
  • Spree::Order::Checkout is not used anymore. Spree::Core::StateMachines::Order is identical.
  • Spree::Admin::PaymentsHelper module is empty after removing all deprecated methods inside it.
  • UserPaymentSource is empty after removing all deprecated methods inside it.
  • Spree::Refund#perform_after_create attribute, it was into a deprecated path. If you are still using it, please stop, it does nothing now.
  • Spree::TaxCalculator#ShippingRate: it is always nil now.
  • Spree::Money::RUBY_NUMERIC_STRING: was only used in a deprecated code path.

We also removed the following preferences without deprecations. They were just controlling a deprecated flow and have no effect so, assuming you already switched to the only accepted value, you can safely remove them from your initializer. You'll probably notice that because your app won't start.

  • Spree::Config.raise_with_invalid_currency
  • Spree::Config.redirect_back_on_unauthorized preference
  • Spree::Config.run_order_validations_on_order_updater preference
  • Spree::Config.use_legacy_order_state_machine
  • Spree::Config.use_legacy_store_credit_reimbursement_category_name
  • Spree::Config.consider_actionless_promotion_active
  • Spree::Config.use_legacy_address_state_validator
  • Spree::Config.use_combined_first_and_last_name_in_address

By default, do not require the whole Rails framework

This shouldn't give any issue in host applications, but if that happens, it can be easily fixable opening config/application.rb and add require 'rails/all' or the specific part of Rails needed by the application.

  • Only require the necessary Rails frameworks #3478 (elia)

Switch Paperclip dependency to its maintained version

We recently added support for Active Support, which will be the default in Solidus 3.0. Paperclip will still be around and supported for a while because we don't want to force existing stores to accomplish the assets migration. While we support it, we want to use the maintained fork.


Solidus 2.11.14 (v2.11, 2021-12-20)

Solidus 2.11.13 (v2.11, 2021-12-07)

Solidus 2.11.12 (v2.11, 2021-11-17)

  • Monkey patch Authentication Bypass by CSRF Weakness vulnerability on solidus_auth_devise for extra security GHSA-5629-8855-gf4g

Solidus 2.11.11 (v2.11, 2021-09-10)

Solidus 2.11.10 (v2.11, 2021-05-10)

  • Use symbols in polymorphic path for event_links #4048 (tvdeyen)

Solidus 2.11.9 (v2.11, 2021-04-20)

Solidus 2.11.8 (v2.11, 2021-04-01)

  • Deprecate calling preferences without serialization #4013 (mamhoff)

Solidus 2.11.7 (v2.11, 2021-03-18)

  • Use Spree.user_class instead of Spree::LegacyUser in production code #3995 (mamhoff)

Solidus 2.11.6 (v2.11, 2021-03-18)

Solidus 2.11.5 (v2.11, 2021-03-09)

Solidus 2.11.4 (2021-01-19)

Solidus 2.11.3 (2020-11-18)

  • Fix reassign image to another variant in admin #3810 (felixyz)
  • Remove seeds for images associated to master variant #3805 (aleph1ow)
  • Check for edit permission when showing store credit edit link #3843 (spaghetticode)
  • Use the right method in the AddApplyToAllToVariantPropertyRule migration #3815 (ok32)
  • Fix permissions to see admin menu items #3840 (kennyadsl)
  • Avoid asking user to run migration creating the sandbox #3839 (kennyadsl)

Solidus 2.11.2 (2020-11-12)

  • Fix ability to perform refunds after a first failed attempt #3831 (kennyadsl)

Solidus 2.11.1 (2020-11-6)

Solidus 2.11.0 (2020-10-23)

Major Changes

Removed support for Rails 5.1

Rails 5.1 is not maintained anymore, we deprecated it in 2.10 so it's time to remove it entirely.

Add billing_address_required preference

The new preference controls whether validations will require the presence of the billing address.

  • Allow to specify if billing address is required for orders #3658 (softr8)

Add BCC email to order confirmation emails

Spree::Store model now accepts a BCC email field that, when present, will be used in order confirmation emails.

Order merger and order updater now require valid order

The order merger and order updater will complete successfully only on valid orders. This new behavior is opt-in with this release, but will become the default from Solidus 3.0.

You can enable this feature right now by setting the preference with Spree::Config.run_order_validations_on_order_updater = true

Stop calling Spree::Refund#perform! after creating a refund

From Solidus v3.0 onwards, #perform! will need to be explicitly called when creating new refunds. Please, change your code from:

Spree::Refund.create(your: attributes)


Spree::Refund.create(your: attributes, perform_after_creation: false).perform!

The perform_after_creation attribute will be deprecated in Solidus 3.x.

  • Stop calling perform! as Spree::Refund after_create callback #3641 (kennyadsl)

Allow to configure guest_token cookie options

The guest_token cookie is currently always only allowed for the current domain, including subdomain. If you want to use the cookie on a different subdomain you can use the preference guest_token_cookie_options.

  • Allow to configure guest_token cookie options #3621 (tvdeyen)

Add event subscribers automatically

Event subscribers are now loaded automatically when their source file is placed under the directory app/subscribers and filename ends with _subscriber.rb. This works both for Solidus core, Solidus extensions and the store app.

If you have any custom subscribers with an explicit subscription (i.e. MyCustomSubscriber.subscribe!) ensure they're under app/subscribers path and remove the explicit subscriptions from your app initializer (i.e MyCustomSubscriber.subscribe!).

Add address default for billing as well

It's now possible to mark an address as default for billing with the column default_billing.

  • Uniform bill_address and ship_address behaviour in Spree::UserAddressBook module #3563 (oldjackson)

Getting closer to completely replace Paranoia with Discard

We're getting closer to fully replace Paranoia with Discard. Paranoia methods have been fully deprecated, so you're encouraged to switch to Discard also in your store codebase.

  • DRY paranoia and discard inclusion into models #3555 (cedum)
  • Replace Paranoia methods with Discard equivalents #3554 (cedum)

Add ActiveStorage adapter

From Rails 6.1 ActiveStorage will support public blob URLs and Solidus should be ready to offer an ActiveStorage adapter to new stores.

Introduce Address#name

We're going to introduce the new column name for addresses that will replace the existing first_name and last_name. In preparation of this, we're now introducing a virtual attribute name that works like and replaces #full_name.

Replace Spree.routes with Spree.pathFor The use of Spree.routes is now deprecated. You can check in your browser developer tools console for deprecation messages.

Configurable order state machine with new default The order state machine class is now configurable, just like other models state machines. Also, a simplified version of the current state machine will be the new default in Solidus 3.x.

  • Configurable order state machine and reduce the number of possible transitions #3542 (mamhoff)

Include payment methods in installer Solidus installer has now a section for installing payment method gems out of the box. Currently, the only available gem is solidus_paypal_commerce_platform.

  • Add payment method selection to the install generator #3731 (elia)

Remove CanCanCan custom actions aliases CanCanCan custom action aliases have been deprecated and replaced with default ones to make it easier upgrading to newer versions of CanCanCan. A new application preference has been introduced: use_custom_cancancan_actions which when set to:

  • true will still accept using custom aliases (default for existing applications);
  • false any custom aliases defined previously won't be handled anymore by Solidus.

Ensure double-checking all the custom defined permissions in your application before switching to use_custom_cancancan_actions preference to false.

Introduce encrypted preference type A new preference type encrypted_string has been introduced allowing to encrypt the value assigned to the preference to avoid exposing it in case a malicious user gets access to the DB or a dump. Check the related guide for more details .

Add "discontinue on" attribute to products Adds a discontinue_on attribute to products. This accompanies the available_on attribute to complete the "Time Based Availability" feature. The Product.available scope and Product#avaliable? method take this new date field into account to calculate the availability of products.

Fixed how the default reimbursement store-credit category is fetched Before this change the store-credit category for reimbursement was fetched by name using a missing translation (i.e. en.spree.store_credit_category.default) that resulted in the name "Default". If no category was found the code fell back on the first category from the database, which wasn't guaranteed to be the right one. Trying to update the translation to the desired category name was also useless due to how code was loaded. Now it's possible to disable this legacy behavior and switch to a simpler one, in which the code will look for a CreditCategory named "Reimbursement". Here's a list of checks and fixes you can perform to ensure you can enable the correct implementation:

  • If you don't use reimbursements you're good to go, skip below to Disabling the legacy behavior
  • Ensure you didn't decorate or patched any of the involved code, especially:
    • Spree::StoreCreditCategory.reimbursement_category
    • Spree::StoreCreditCategory.reimbursement_category_name
  • Ensure your "production" environment is already returning the correct category, you can assess that by running this in your "production" console: Spree::StoreCreditCategory.reimbursement_category(nil).name == "Reimbursement"

Disabling the legacy behavior If everything is sound, or you are ok with a different category name for newly created reimbursement store credits you can switch to the new behavior by configuring this Solidus preference in your spree.rb initializer:

Spree.config do |config|
  config.use_legacy_store_credit_reimbursement_category_name = false

If you had modifications in your codebase consider disabling the legacy behavior and porting them to a simple overwrite of Spree::Reimbursement#store_credit_category. The legacy behavior will be removed in the next major version of Solidus.

  • Fix reimbursement_category_name ending up in a translation missing error #3507 (elia)

Do not consider promotions without actions as active

When considering to apply a promotion to an order we use the active scope. This scope was including promotions without actions and we no longer are taking them into account.

To switch to the new behaviour which will be the only one accepted in Solidus 3.0 change the following preference Spree::Config.consider_actionless_promotion_active to false.

If you need to consider actionless promotions as active for any reason please implement your own scope for that.



  • Fix Ruby 2.7 warnings on backend #3746 (stefano-sarioli)
  • Respect current ability in users controllers #3732 (igorbp)
  • [Admin] Disallow promotions with empty action type and discount rule #3724 (cnorm35)
  • Replace duplicate data-hook name #3705 (seand7565)
  • Change to true/false to yes/no in Auto Capture Select Text #3703 (michaelmichael)
  • [Admin] Fix Square Logos appearance #3702 (michaelmichael)
  • [Admin] Add filter feature for stock movements #3680 (jacquesporveau)
  • Display originator email in stock movement admin #3673 (jacquesporveau)
  • [Backend] More precise cancan validations for some resource links #3654 (spaghetticode)
  • Variant property rules to optionally match all conditions (cont.) #3653 (filippoliverani)
  • Eager loading countries when creating a new zone #3649 (softr8)
  • Remove unused XHR code #3642 (halilim)
  • Admin UI for shipping methods - stock locations association #3624 (cedum)
  • Refactoring Admin::ProductsController to use ResourcesController#update #3603 (softr8)
  • Rescuing from ActiveRecord::RecordInvalid in ResourcesController #3602 (softr8)
  • Adding missing paginator when listing all stock locations #3600 (softr8)
  • Show only active promotions filter #3595 (wildbillcat)
  • Unified Handling of Option Values and Product Properties List #3592 (hefan)
  • Do not pass non persistent new records when sorting tables by removing non numeric ids #3591 (hefan)
  • Check if promotions exist without extra db query #3586 (katafrakt)
  • Do not display non-eligible adjustments in the admin cart overview #3585 (coorasse)
  • Backend: more robust update_positions for resource controller #3581 (hefan)
  • [Backend] Handle errors and flash messages editing a taxon #3574 (softr8)
  • Remove non-existing middleware #3570 (coorasse)
  • Add ability to select multiple rows on Admin Tables #3565 (DanielePalombo)
  • Add support for prefill user address in new order #3558 (jaimelr)
  • replace link_to_add_fields usage and deprecate helper function #3547 (hefan)
  • Convert ES6 arrow syntax to ES5 for compatibility #3511 (pelargir)
  • Ensure payment methods are ordered correctly #3506 (AlistairNorman)
  • [Admin] Change shipment email checkbox label #3490 (kennyadsl)
  • Use RESTful routing for users' API key management #3442 (kennyadsl)
  • Fix issue 3164 - generate shipments for backend-added products when necessary #3197 (spaghetticode)
  • Fixes for consistent handling of resource errors on admin #3728 (ikraamg)
  • Expose js function: Spree.SortableTable.refresh #3754 (brunoao86)
  • Fix TaxCategory default not showing up in admin #3759 (vl3)
  • Make order customer email links consistent #3767 (brchristian)
  • Fix typo in comment in navigation_helper.rb #3770 (brchristian)
  • Make admin order event_links translatable #3772 (tvdeyen)
  • Display billing address to left of shipping address #3773 (brchristian)
  • Add hint to tax category default checkbox #3778 (pelargir)
  • Add link to stock movements page from variant stock display #3779 (seand7565)
  • Update backend New Image link for consistency #3786 (brchristian)
  • Show the admin/settings menu for any of its elements #3783 (elia)
  • Improve the developer experience with the new Ability deprecations #3801 (elia)
  • Ensure #resource_not_found mentions the right model #3798 (elia)
  • Add CSS selector for datetime-local #3792 (jacobherrington)
  • Remove CSS resizing logo when menu collapses #3791 (jacobherrington)


  • Allow for HTML options on image partial #3741 (markmead)
  • Use a better name for CheckoutController#set_state_if_present #3496 (elia)
  • Replace with :all_adjustments.nonzero.any? #3787 (duartemvix)


Deprecations & Removals


Docs & Guides

Solidus 2.10.5 (v2.10, 2021-05-10)

  • Use symbols in polymorphic path for event_links #4048 (tvdeyen)

Solidus 2.10.1 (2020-05-14)

  • Fix in_taxons scope when taxon is an ActiveRecord::Base 3617 (kennyadsl)

Solidus 2.10.0 (2020-01-15)

Major Changes

Added support for Rails 6

Solidus core now fully support Rails 6! After upgrading to the 2.10 you can follow the official Rails Upgrading Guide here: Please note that Rails 6 requires Ruby 2.5.0 or newer.

Deprecated support for Rails 5.1

Rails 5.1 is deprecated and we'll remove support to 5.1 on the next version. If you are still using it, a deprecation warning will be printed in your logs when the application boots.

Changed default images sizes

We update the images used by Solidus demo in the sample gem. To update those images we needed to change the default sizes of Spree::Image. They changed from:

mini: '48x48>', small: '100x100>', product: '240x240>', large: '600x600>'


mini: '48x48>', small: '400x400>', product: '680x680>', large: '1200x1200>'

If your store relies on these sizes, you should change them back following the guide here:

State machines extracted into their own replaceable modules

This allows stores to replace the state machine completely with their own implementation, even with different gems or using custom code without any state machine gem. All the customizations previously made to the state machine should work smoothly, but it could be a good idea to check twice. You can read more about the suggested way to customize the state machine here:

  • Extract the state machines into replaceable modules #3356 (cedum)

Display error if editing non-current order

In Solidus frontend users were able to input any order_id in the /orders/:order_id/edit route and they were simply seeing the cart (showing the current order and not the requested one) without any notice. With this Solidus version we print an flash message and redirect users to their cart.

  • Display error if editing non-current order #3391 (JDutil)

Solidus now requires Ruby 2.4 or newer

Ruby 2.2 and 2.3 support has ended, Rubocop support for 2.2 ended and they are also about to drop 2.3. Also, we already introduced code that is not compliant with 2.2 anymore.




  • Fix Coupon Code Field's Length in Firefox #3387 (amree)


Deprecations & Removals


Docs & Guides

Solidus 2.9.0 (2019-07-16)

Major Changes

Added Spree::Event

Solidus now includes an event library that allows to use different adapters. The default adapter is based on ActiveSupport::Notifications library. Events should allow developers to customize and extend Solidus behavior more easily by simply subscribing to certain events. Sending emails may be a simple use case for this new feature.

Attachment adapters

This is the first step to support other files attachment libraries since Paperclip is no more maintained. Solidus will release the ActiveStorage support in core in the next releases or via an extension.

Add more fields to the API json response for shipments

This change adds more fields to the API endpoints that return a shipment object. We had two partials to represent shipments: small and big but some of the small fields were not present in the big partial. Now they are aligned but users that were using those partials could notice some difference in how the API endpoints involved respond.

  • Complete Shipments Big json with small json fields #3221 (JuanCrg90)

Deprecate reset_spree_preferences in test

Changing preferences and resetting them after any example is not a good practice and it's error-prone. The new standard is stubbing preferences and it's enforced with a deprecation of reset_spree_preferences. This way we can gradually align stores and extensions.

Changed payment method partials name convention

Payment methods partials filename are now expected to be the Spree::PaymentMethod class underscored instead of downcased. This means that, for example, for Spree::PaymentMethod::StoreCredit the corresponding partial files would be named _store_credit and not _storecredit. If you overrode one of the following files, you should rename it now:

api/app/views/spree/api/payments/source_views/_storecredit.json.jbuilder → api/app/views/spree/api/payments/source_views/_store_credit.json.jbuilder
backend/app/views/spree/admin/payments/source_forms/_storecredit.html.erb → backend/app/views/spree/admin/payments/source_forms/_store_credit.html.erb
backend/app/views/spree/admin/payments/source_views/_storecredit.html.erb → backend/app/views/spree/admin/payments/source_views/_store_credit.html.erb

Also, if you've built your own payment method you may need to change the corresponding partials filename.

Fix non thread safe gateway initialization

ActiveMerchant::Billing::Base.mode is a global ActiveMerchant preference and we were setting it into each payment gateway initialization. This means that if the last instantiated payment method's mode was different from the other ones, the last one's mode will be applied to all of them. To fix this issue we changed how we tell ActiveMerchant that one gateway is in test mode. Please double check your production configuration for payment methods: only payment methods where server preference set to production and test_mode turned off will work in "production" mode.

Remove name from default ransackable attributes

Ransack needs a whitelist of attributes to perform a search against for security reasons. We used to whitelist id and name for all the models but not all models have the name attribute/column making ransack search raise an error. If you have a custom model and you are performing search against its name, now you have to manually add it to the ransackable whitelist for that resource.

  • Remove name column from default ransackable attributes #3180 (mdesantis)

Admin restyle

Solidus has a fresh Admin UI! Your eyes will thank you and this would not impact your store but if you added some custom CSS that matches the old Admin UI, you probaly have to make some change at it now.

Changes to how returns are processed from a return item

It you are programmatically calling Spree::ReturnItem#process_inventory_unit! please notice that it doesn't automatically process return anymore. To remove the deprecation warning you have to set an attribute on your return_item instance before calling process_inventory_unit!:

return_item.skip_customer_return_processing = true
# here you should process the customer return manually

New REST API documentation

Our REST API is now documented using the Open API Specification. The documentation is part of the repository and published on





  • Use classes alongside data-hook attributes for gateway partial #3182 (aitbw)



Docs & Guides

Solidus 2.8.0 (2019-01-29)

Major Changes

Added Api::CouponCodesController#destroy endpoint

A new endpoint has been added to Solidus API. It allows to remove a coupon code from an order. It has currently no backend or frontend implementation but it's common for custom stores to require it.

  • Add Api::CouponCodesController#destroy endpoint #3047 (aitbw)

Moved Reports into an extension

We removed the reports section from admin to an extension. If you use it you have to add it back manually by adding

gem 'solidus_reports', github: "solidusio-contrib/solidus_reports"
  • Move reports from backend into an extension #2814 (jtapia)

Add a store credit reasons UI in Admin

The only way to manage store credit reasons was via console or using a data migration.

Skip forgery protection in api controllers

Rails is now enabling forgery protection by default so we need to explicitly disable it for api requests, as described here:

This PR also enables forgery protection by default in the specs dummy app so that we can really test that the api code is working in a real Rails 5.2+ environment.

Add a Gallery to handle variants and products images

All images that we send to the view layer is now using these classes that contain the logic to retrieve images and are easier to extend. If you have a lot of customization on how you display images you probably need to take a look at how this has been implemented.

Replace jquery_ujs with rails-ujs

This is the Rails standard now. There could be some action required, depending on if the manifest provided by solidus has been changed. Please read the PR description for more info.

  • Replace jquery_ujs with rails-ujs in frontend and backend #3027 (kennyadsl)

Removed code from Spree::Promotion

Previously Solidus used code column on spree_promotions to add a code to promotions that could be used as coupon code by users. This is no more a thing since we support multiple coupon codes associated to a single promotion.

This change is important because it's quite common for old stores to have some promotion with code field still present in the database, even if it's not used. When performing the migration present in this PR it will raise an exception if there are records in the spree_promotions table with that field present. It's up to each store to understand how to handle this scenario before running this migration. We also provide other two ways to handle this, and users can just change the migration after it has been copied into their store. It's just matter of changing the content of the RemoveCodeFromSpreePromotions.promotions_with_code_handler method and make it return one of the following:

  • Solidus::Migrations::PromotionWithCodeHandlers::MoveToSpreePromotionCode: it will convert Spree::Promotion#code to a Spree::PromotionCode before removing the code column.
  • Solidus::Migrations::PromotionWithCodeHandlers::DoNothing: it will print a message to track what we are deleting.

Alternatively users can create their own class to handle data and return that class. The new class could inherit from PromotionsWithCodeHandler and should respond to call.




  • Fix N+1 problem on Api::TaxonsController#index #3011 (stem)
  • Include records on API Order / Product queries #3002 (fastjames)



  • Deprecate 'X-SPREE-TOKEN' header 2 #3029 (twist900)
  • Update Jbuilder to v2.8 to fix deprecation warnings #2962 (aitbw)
  • Deprecate existing coupon codes methods #2958 (aitbw)
  • Fix deprecation warning for Spree::Shipment#reverse_chronological scope #2921 (aitbw)
  • Add deprecation warning for Spree.t #2915 (JDutil)


Docs & Guides

Solidus 2.7.0 (2018-09-14)

Major Changes

Rails 5.2.1

Added support for Rails 5.2.1. Solidus 2.7.0 supports either Rails 5.2.x or 5.1.


Added the new guides website code directly into the main repository. This way it should be simpler to keep guides up to date.



  • Set correct quantity on order import #2837 (fastjames)
  • Money#allocate calculates weights already #2836 (huoxito)
  • Update user_class_handle.rb #2832 (bazfer)
  • Allow customizing the promotion code batch mailer class #2796 (jtapia)
  • Allow customizing the reimbursement mailer class #2795 (jtapia)
  • Allow customizing the order mailer class #2792 (jtapia)
  • Compatibility with Rails 5.2.1 & Ransack #2826 (kennyadsl)
  • Move factory_bot static attrs to dynamic #2831 (fastjames)
  • Use Spree.user_class.table_name instead of spree_users #2815 (masatooba)
  • Fix a store credit spec that is time zone dependent #2778 (kennyadsl)
  • Making sure order by columns do not collide with other tables #2774 (softr8)
  • Fix permissions for users to change their own orders #2787 (kennyadsl)


  • Fix space between taxons on admin taxonomies #2812 (jtapia)
  • Fix issue not updating payment method type on admin #2788 (jtapia)
  • Tracking Number link to Tracking URL page #2829 (JuanCrg90)
  • make customer email field required when an admin is making a new order #2771 (jacobherrington)
  • Fix bug with user address forms #2766 (jacobeubanks)
  • Dynamically render ReportsController translations #2751 (stewart)
  • Add missing data-hook on customer_returns tab #2738 (fkoessler)
  • Require sass >= 3.5.2 #2734 (gmacdougall)
  • The promotions "Advertise" checkbox and the "URL Path" promotion activation method have been removed from the admin UI because the features are not implemented in solidus_frontend #2737 (benjaminwil)
  • Use a different session key for admin locale #2685 (jhawthorn)
  • Disable backend footer profile edit link if role cannot edit users #2646 (gianlucarizzo)
  • Improve admin return authorization controller #2420 (kennyadsl)


  • The TaxonsController#show action loads now the @taxon in a before_action callback. This means that if you overrode the show method you may be loading the @taxon variable twice. You can now change the behaviour of how the @taxon is loaded overriding the load_taxon method instead. #2782 (coorasse)
  • Move checkout coupon code section into summary. Now passing [:order][:coupon_code] into any controller of the frontend will not perform any action, while it was trying to add a new coupon code before. It now only works in checkout and orders controller. #2327 (kennyadsl)

Solidus 2.6.0 (2018-05-16)

Major changes

Rails 5.2

This is the first version of Solidus to support Rails 5.2. Solidus 2.6.0 supports either Rails 5.1 or 5.2. We're hoping this makes both upgrades as easy as possible since they can be done separately.

Merged solidus_i18n functionality

Much of solidus_i18n's functionality has been merged into Solidus itself. Solidus now allows configuring one or more locales per-store in the admin. Both users and admins can select their preferred locales on the frontend or admin respectively. More information on how to upgrade can be found in the solidus_i18n README.


A lot of work has gone into guides, which are now much more comprehensive. A website to host them is in the works but for now they can be seen on github






Solidus 2.5.0 (2018-03-27)

Major Changes

Migrate to discard from paranoia

Previously Solidus used paranoia to handle soft-deletion.

paranoia, on acts_as_paranoid models, replaces ActiveRecord's delete and destroy methods and instead of deleting the record sets the deleted_at column. This has been the cause of some surprising behaviour for users old and new.

In this version we are beginning to deprecate this using the discard gem.

solidus_stock_transfers extracted to gem

solidus_stock_transfers provides an admin interface to transfer stock between two locations. This used to be included in core but has been extracted to a gem.


Deprecations and removals


  • Replace frontend jquery validations with html5 #2264 (cbrunsdon, jhawthorn)

    We've removed jquery validations on checkout address form, replacing them with html5 input validations. If your store relies on jquery validation you should re-add that library in your store. Otherwise, if you use the old view version (without required: true attributes on input) your address form will not be validated on client side.

  • Remove render_404 from frontend #2329 (jhawthorn)

  • Add frontend login_bar_items placeholder partial #2308 (jhawthorn)

  • Use product image template in frontend #2300 (swcraig)

  • Remove required attribute from address lastname #2393 (kennyadsl)

  • Convert frontend's CoffeeScript to javascript #2378 (jhawthorn)

  • Convert Cart total/subtotal CSS colors to vars #2288 (gregdaynes)

  • Fixed caching of taxon menu. #2317 (bofrede)

  • Use empty? instead of length == 0 #2282 (brchristian)

  • Use line_item_adjustments in spree/shared/_order_details #2257 (cbrunsdon)

  • Filter unpriced products in taxon_preview #2604 (jhawthorn)

  • Fix error when listing products without price #2605 (jhawthorn)




Solidus 2.4.0 (2017-11-07)

Major changes

  • Replace RABL with Jbuilder #2147 #2146 (jhawthorn)

    We've changed our JSON templating language for both the API and admin from RABL to Jbuilder. Jbuilder is faster and much more widely used (ships with Rails).

    API responses should be identical, but stores which customized API responses using RABL or added their own endpoints which extended Solidus' RABL partials will need to be updated.

  • Remove rescue_from StandardError in Api::BaseController #2139 (jhawthorn)

    Previously, exceptions raised in the API were caught (via rescue_from) and didn't reach the default Rails error handler. This caused many exceptions to avoid notice, both in production and in tests.

    This has been removed and exceptions are now reported and handled normally.

  • New admin table design #2159 #2100 #2143 #2123 #2165 (Mandily, graygilmore, tvdeyen)

    Tables throughout the admin have been redesigned to be simpler and clearer. Borders between cells of the same row have been dropped, row striping has been removed, and icons are simpler and more clearly attached to their row.

  • Introduce Stock::SimpleCoordinator #2199 (jhawthorn)

    The previous stock coordinator had incorrect behaviour when any stock location was low on stock.

    The existing stock coordinator classes, Coordinator, Adjuster, Packer, and Prioritizer, have been replaced with the new Stock::SimpleCoordinator. In most cases this will coordinate stock identically to the old system, but will succeed for several low-stock cases the old Coordinator incorrectly failed on.

    Stores which have customized any of the old Coordinator classes will need to either update their customizations or include the solidus_legacy_stock_system extension, which provides the old classes.


  • Replace Stock::Coordinator with Stock::SimpleCoordinator #2199 (jhawthorn)

  • Wrap Splitter chaining behaviour in new Stock::SplitterChain class #2189 (jhawthorn)

  • Remove Postal Code Format Validation (and Twitter CLDR dependency) #2233 (mamhoff)

  • Switch factories to strings instead of constants #2230 (cbrunsdon)

  • Roll up migrations up to Solidus 1.4 into a single migration #2229 (cbrunsdon)

  • Support non-promotion line-level adjustments #2188 (jordan-brough)

  • Fix StoreCredit with multiple currencies #2183 (jordan-brough)

  • Add Spree::Price to ProductManagement role #2182 (swcraig)

  • Remove duplicate error on StoreCredit#authorize failure #2180 (jordan-brough)

  • Add dependent: :destroy for ShippingMethodZones join model #2175 (jordan-brough)

  • Fix method missing error in ReturnAuthorization#amount #2162 (luukveenis)

  • Use constants instead of translations for StoreCreditType names #2157 (swcraig)

  • Enable custom shipping promotions via config.spree.promotions.shipping_actions #2135 (jordan-brough)

  • Validate that Refunds have an associated Payment #2130 (melissacarbone)

  • Include completed payment amounts when summing totals for store credit #2129 (luukveenis)

  • Allow dev mode code reloading of configured classes #2126 (jhawthorn)

  • Override model_name.human for PaymentMethod #2107 (jhawthorn)

  • Fix class/module nesting #2098 (cbrunsdon)

  • Reduce number of SQL statements in countries seeds #2097 (jhawthorn)

  • Rename Order#update! to order.recalculate #2072 (jhawthorn)

  • Rename Adjustment#update! to Adjustment#recalculate #2086 (jhawthorn)

  • Rename Shipment#update! to Shipment#update_state #2085 (jhawthorn)

  • Fix shipping method factory for stores with alternate currency #2084 (Sinetheta)

  • Added a configurable Spree::Payment::Cancellation class #2111 (tvdeyen)

  • Remove set_current_order calls in Spree::Core::ControllerHelpers::Order #2185 (Murph33)

    Previously a before filter added in core/lib/spree/core/controller_helpers/order.rb would cause SQL queries to be used on almost every request in the frontend. If you do not use Solidus Auth you will need to hook into this helper and call set_current_order where your user signs in. This merges incomplete orders a user has going with their current cart. If you do use Solidus Auth you will need to make sure you use a current enough version (>= v1.5.0) that includes this explicit call. This addresses #1116.

  • Remove ffaker as a runtime dependency in production. It needs to be added to the Gemfile for factories to be used in tests #2163 #2140 (cbrunsdon, swcraig)

  • Invalidate existing non store credit payments during checkout 2075 (tvdeyen)

  • The all configuration objects now use static preferences by default. It's no longer necessary to call use_static_preferences!, as that is the new default. For the old behaviour of loading preferences from the DB, call config.use_legacy_db_preferences!. #2112 (jhawthorn)

  • Assign and initialize Spree::Config earlier, before rails initializers #2178 (cbrunsdon)


  • Replace RABL with Jbuilder #2147 #2146 (jhawthorn)
  • Move API pagination into a common partial #2181 (jhawthorn)
  • Fix references to nonexistent API attributes #2153 (jhawthorn)
  • Remove rescue_from StandardError in Api::BaseController #2139 (jhawthorn)
  • Fix error when passing coupon_code to api/checkouts#update #2136 (jhawthorn)
  • Improved error handling and performance for moving inventory units between shipments and stock locations #2070 (mamhoff)
  • Remove unnecessary Api::Engine.root override #2128 (jhawthorn)





  • Deprecate .calculators #2216 (cbrunsdon)
  • Deprecate pagination in searcher #2119 (cbrunsdon)
  • Deprecate tasks in core/lib/tasks #2080 (cbrunsdon)
  • Deprecate Spree::OrderCapturing class #2076 (tvdeyen)
  • Deprecated Spree::PaymentMethod#cancel #2111 (tvdeyen) Please implement a try_void method on your payment method instead that returns a response object if void succeeds or false if not. Solidus will refund the payment then.
  • Deprecates several preference fields helpers in favor of preference field partials. #2040 (tvdeyen) Please render spree/admin/shared/preference_fields/#{preference_type} instead
  • Check if deprecated method_type is overridden #2093 (jhawthorn)
  • Deprecate support for alternate Kaminari page_method_name #2115 (cbrunsdon)
  • Deprecate update_params_payment_source method #2227 (ccarruitero)

Solidus 2.3.0 (2017-07-31)

  • Rails 5.1 #1895 (jhawthorn)

  • The default behaviour for selecting the current store has changed. Stores are now only returned if their url matches the current domain exactly (falling back to the default store) #2041 #1993 (jhawthorn, kennyadsl)

  • Remove dependency on premailer gem #2061 (cbrunsdon)

  • Order#outstanding_balance now uses reimbursements instead of refunds to calculate the amount that should be paid on an order. #2002 (many contributors ❤️)

  • Renamed bogus payment methods #2000 (tvdeyen) Spree::Gateway::BogusSimple and Spree::Gateway::Bogus were renamed into Spree::PaymentMethod::SimpleBogusCreditCard and Spree::PaymentMethod::BogusCreditCard

  • Allow refreshing shipping rates for unshipped shipments on completed orders #1906 (mamhoff)

  • Remove line_item_options class attribute from Api::LineItemsController #1943

  • Allow custom separator between a promotion's base_code and suffix #1951 (ericgross)

  • Ignore adjustment.finalized on tax adjustments. #1936 (jordan-brough)

  • Transform the relation between TaxRate and TaxCategory to a Many to Many #1851 (vladstoick)

    This fixes issue #1836. By allowing a TaxRate to tax multiple categories, stores don't have to create multiple TaxRates with the same value if a zone doesn't have different tax rates for some tax categories.

  • Adjustments without a source are now included in line_item.adjustment_total #1933 (alexstoick)

  • Always update last_ip_address on order #1658 (bbuchalter)

  • Don't eager load adjustments in current_order #2069 (jhawthorn)

  • Avoid running validations in current_order #2068 (jhawthorn)

  • Fix Paperclip::Errors::NotIdentifiedByImageMagickError on invalid image #2064 (karlentwistle)

  • Fix error message on insufficient inventory. #2056 (husam212)

  • Remove print statements from migrations #2048 (jhawthorn)

  • Make Address.find_all_by_name_or_abbr case-insensitive #2043 (jordan-brough)

  • Remove redundant methods on Spree::PaymentMethod::StoreCredit #2038 (skukx)

  • Fix ShippingMethod select for MySQL 5.7 strict #2024 (jhawthorn)

  • Use a subquery to avoid returning duplicate products from Product.available #2021 (jhawthorn)

  • Validate presence of product on a Variant #2020 (jhawthorn)

  • Add some missing data to seeds which was added by migrations #1962 (BravoSimone)

  • Add validity period for Spree::TaxRate #1953 (mtylty)

  • Remove unnecessary shipping rates callback #1905 (mamhoff)

  • Remove fallback first shipping method on shipments #1843 (mamhoff)

  • Add a configurable order number generator #1820 (tvdeyen)

  • Assign default user addresses in checkout controller #1967 (kennyadsl)

  • Use user.default_address as a default if bill_address or ship_address is unset #1424 (yeonhoyoon, peterberkenbosch)

  • Add html templates for shipped_email and inventory_cancellation emails #1377 (DanielePalombo)

  • Don't @extend compound selectors in sass. Avoids deprecation warnings in sass 3.4.25 #2073 (jhawthorn)


  • Configure admin turbolinks #1882 (mtomov)
  • Allow users to inline update the variant of an image in admin #1580 (mtomov)
  • Fix typo on fieldset tags #2005 (oeN)
  • Use more specific selector for select2 #1997 (oeN)
  • Replace select2 with <select class="custom-select"> #2034 #2030 (jhawthorn)
  • Fix admin SQL issues with DISTINCT products #2025 (jhawthorn)
  • Use @collection instead of @collection.present? in some admin controllers #2046 (jordan-brough)
  • Admin::ReportsController reusable search params #2012 (oeN)
  • Do not show broken links in admin product view when product is deleted #1988 (laurawadden)
  • Allow admin to edit variant option values #1944 (dividedharmony)
  • Do not refresh shipping rates everytime the order is viewed in the admin #1798 (mamhoff)
  • Add form guidelines to the style guide #1582 (Mandily)
  • Improve style guide flash messages UX #1964 (mtylty)
  • Document tooltips in the style guide #1955 (gus4no)
  • Fix path for distributed amount fields partial #2023 (graygilmore)
  • Use .all instead of .where\(nil\) in Admin::ResourceController #2047 (jordan-brough)
  • Fix typo on the new promotions form #2035 (swcraig)
  • Use translated model name in admin payment methods form #1975 (tvdeyen)


  • Renamed Spree::Gateway payment method into Spree::PaymentMethod::CreditCard #2001 (tvdeyen)
  • Deprecate #simple_current_order #1915 (ericsaupe)
  • Deprecate PaymentMethod.providers in favour of Rails.application.config.spree.payment_methods #1974 (tvdeyen)
  • Deprecate Spree::Admin::PaymentMethodsController#load_providers in favour of load_payment_methods #1974 (tvdeyen)
  • Deprecate Shipment#add_shipping_method #2018 (jhawthorn)
  • Re-add deprecated TaxRate#tax_category #2013 (jhawthorn)
  • Deprecate Spree::Core::CurrentStore in favor of Spree::CurrentStoreSelector. #1993
  • Deprecate Spree::Order#assign_default_addresses! in favor of #1954 (kennyadsl)
  • Rename PaymentMethod#method_type into partial_name #1978 (tvdeyen)
  • Remove ! from assign_default_user_addresses!, deprecating the old method #2019 (jhawthorn)
  • Emit Spree.url JS deprecation warning in all environments #2017 (jhawthorn)

Solidus 2.2.1 (2017-05-09)

  • Fix migrating CreditCards to WalletPaymentSource #1898 (jhawthorn)
  • Fix setting the wallet's default payment source to the same value #1888 (ahoernecke)
  • Fix assigning nil to default_wallet_payment_source= #1896 (jhawthorn)

Solidus 2.2.0 (2017-05-01)

Major Changes

  • Spree::Wallet and Non credit card payment sources #1707 #1773 #1765 (chrisradford, jordan-brough, peterberkenbosch)

    This adds support for payment sources other than CreditCard, which can be used to better represent other (potentially reusable) payment sources, like PayPal or Bank accounts. Previously sources like this had to implement all behaviour themselves, or try their best to quack like a credit card.

    This adds a PaymentSource base class, which CreditCard now inherits, and a Wallet service class to help manage users' payment sources. A WalletPaymentSource join table is used to tie reusable payment sources to users, replacing the existing behaviour of allowing all credit cards with a stored payment profile.

  • Add promotion code batch #1524 (vladstoick)

    Prior to Solidus 1.0, each promotion had at most one code. Though we added the functionality to have many codes on one promotion, the UI for creation and management was lacking.

    In Solidus 2.2 we've added PromotionCodeBatch, a model to group a batch of promotion codes. This allows additional promotion codes to be generated after the Promotion's initial creation. Promotion codes are also now generated in a background job.

  • Admin UI Changes

    The admin UI was once again a focus in this release. We've made many incremental changes we think all users will appreciate. This includes an upgrade to Bootstrap 4.0.0.alpha6, changes to table styles, and a better select style.

    See the "Admin UI" section below for a full list of changes.


  • Spree::Order#available_payment_methods returns an ActiveRecord::Relation instead of an array #1802 (luukveenis)
  • Product slugs no longer have a minimum length requirement #1616 (fschwahn)
  • Spree::Money now includes Comparable and the <=> operator for comparisons. #1682 (graygilmore )
  • Allow destruction of shipments in the "ready" state. #1784 (mamhoff)
  • Do not consider pending inventory units cancelable #1800 (mamhoff)
  • Rewrite spree.js in plain JS #1754 (jhawthorn)
  • Make sensitive params filtering less eager #1755 (kennyadsl)
  • Use manifest.js to support Sprockets 4 #1759 (jhawthorn)
  • Update paperclip dependency #1749 (brchristian)
  • Update kaminari dependency to 1.x #1734 (jrochkind)
  • Allow twitter_cldr 4.x #1732 (jrochkind)
  • Added LineItem name to unavailable flash #1697 (ericsaupe)
  • Don't treat "unreturned exchanges" specially in checkout state machine flow #1690 (jhawthorn)
  • set_shipments_cost is now part of OrderUpdater #1689 (jhawthorn)
  • Methods other than update!, update_shipment_state, update_payment_state are now private on OrderUpdater #1689 (jhawthorn)

Bug Fixes

  • AvailabilityValidator correctly detects out of stock with multiple shipments from the same stock location. #1693 (jhawthorn)
  • Fix missing close paren in variantAutocomplete #1832 (jhawthorn)
  • Set belongs_to_required_by_default = false #1807 (jhawthorn)
  • Fix loading transfer shipments #1781 (mamhoff)
  • Fix complete order factory to have non-pending inventory units #1787 (mamhoff)
  • Fix to cart URL for stores not mounted at root #1775 (funwhilelost)
  • Remove duplicated require in shipment factory #1769 (upinetree)
  • Fix an issue where updating a user in the admin without specifying roles in would clear the existing roles.#1747 (tvdeyen)
  • Fix the 'Send Mailer' checkbox selection #1716 (jhawthorn)
  • Rearrange AR relation declarations in order.rb in preparation for Rails 5.1 #1740 (jhawthorn)
  • Fix issue where OrderInventory creates superfluous InventoryUnits #1751 (jhawthorn)
  • Fix check for order.guest\_token presence #1705 (vfonic)
  • Fix shipped_order factory #1772 (tvdeyen)
  • Don't display inactive payment methods on frontend or backend #1801 (luukveenis)
  • Don't send email if PromotionCodeBatch email is unset #1699 (jhawthorn)



Admin UI


  • Extract expedited exchanges to an extension #1691 (jhawthorn)
  • Remove spree_store_credits column #1741 (jhawthorn)
  • Remove StockMovements#new action and view #1767 (jhawthorn)
  • Remove unused #1768 (jhawthorn)
  • Remove unused payment Javascript #1735 (jhawthorn)
  • Moved spree/admin/shared/_translations partial to spree/admin/shared/_js_locale_data.


  • Deprecate Order#has_step? in favour of has_checkout_step? #1667 (mamhoff)
  • Deprecate Order#set_shipments_cost, which is now done in Order#update! #1689 (jhawthorn)
  • Deprecate user.default_credit_card, user.payment_sources for user.wallet.default_wallet_payment_source and user.wallet.wallet_payment_sources
  • Deprecate CreditCard#default in favour of user.wallet.default_wallet_payment_source
  • Deprecate cache_key_for_taxons helper favour of cache [I18n.locale, @taxons]
  • Deprecate admin sass variables in favour of bootstrap alternatives #1780 (tvdeyen)
  • Deprecate Address#empty? #1686 (jhawthorn)
  • Deprecate fill_in_quantity capybara helper #1710 (jhawthorn)
  • Deprecate wait_for_ajax capybara helper #1668 (cbrunsdon)

Solidus 2.1.0 (2017-01-17)

  • The OrderUpdater (as used by order.update!) now fully updates taxes.

    Previously there were two different ways taxes were calculated: a "full" and a "quick" calculation. The full calculation was performed with order.create_tax_charge! and would determine which tax rates applied and add taxes to items. The "quick" calculation was performed as part of an order update, and would only update the tax amounts on existing line items with taxes.

    Now order.update! will perform the full calculation every time. order.create_tax_charge! is now deprecated and has been made equivalent to order.update!.


  • ItemAdjustments has been merged into the OrderUpdater

    The previous behaviour between these two classes was to iterate over each item calculating promotions, taxes, and totals for each before moving on to the next item. To better support external tax services, we now calculate promotions for all items, followed by taxes for all items, etc.


  • Make frontend prices depend on store.cart_tax_country_iso

    Prices in the frontend now depend on store.cart_tax_country_iso instead of Spree::Config.admin_vat_country_iso.


  • Deprecate methods related to Spree::Order#tax_zone

    We're not using Spree::Order#tax_zone, Spree::Zone.default_tax, Spree::Zone.match, or Spree::Zone#contains? in our code base anymore. They will be removed soon. Please use Spree::Order#tax_address, Spree::Zone.for_address, and Spree::Zone.include?, respectively, instead.


  • Product Prototypes have been removed from Solidus itself.

    The new solidus_prototype extension provides the existing functionality. #1517

  • Analytics trackers have been removed from Solidus itself.

    The new solidus_trackers extension provides the existing functionality. #1438

  • Bootstrap row and column classes have replaced the legacy skeleton classes throughout the admin. #1484

  • Remove currency from line items.

    It's no longer allowed to have line items with different currencies on the same order. This makes storing the currency on line items redundant, since it will always be considered the same as the order currency.

    It will raise an exception if a line item with the wrong currency is added.

    This change also deletes the currency database field (String) from the line_items table, since it will not be used anymore.


  • Add Spree::Promotion#remove_from and Spree::PromotionAction#remove_from

    This will allow promotions to be removed from orders and allows promotion actions to define how to reverse their side effects on an order.

    For now PromotionAction provides a default remove_from method, with a deprecation warning that subclasses should define their own remove_from method.


  • Remove is_default boolean from Spree::Price model

    This boolean used to mean "the price to be used". With the new pricing architecture introduced in 1.3, it is now redundant and can be reduced to an order clause in the currently valid prices scope.


  • Remove callback Spree::LineItem.after_create :update_tax_charge

    Any code that creates LineItems outside the context of OrderContents should ensure that it calls order.update! after doing so.


  • Mark Spree::Tax::ItemAdjuster as api-private #1463

  • Updated Credit Card brand server-side detection regex to support more brands and MasterCard's new BIN range. #1477

    Note: Most stores will be using client-side detection which was updated in Solidus 1.2

  • CreditCard's verification_value field is now converted to a string and has whitespace removed on assignment instead of before validations.

  • The lastname field on Address is now optional. #1369

  • The admin prices listings page now shows master and variant prices seperately. This changes @prices to @master_prices and @variant_prices in prices_controller


  • Admin javascript assets are now individually required using sprockets directives instead of using require_tree. This should fix issues where JS assets could not be overridden in applications. #1613

  • The admin has an improved image upload interface with drag and drop. #1553

  • PaymentMethod's display_on column has been replaced with available_to_users and available_to_admin. The existing attributes and scopes have been deprecated.


  • ShippingMethod's display_on column has been replaced with available_to_users. The existing attributes and scopes have been deprecated.


  • Added experimental Spree::Config.tax_adjuster_class

    To allow easier customization of tax calculation in extensions or applications.

    This API is experimental and is likely to change in a future version.


  • Removals

    • Removed deprecated STYLE_image helpers from BaseHelper #1623

    • Removed deprecated method Spree::TaxRate.adjust (not to be confused with Spree::TaxRate#adjust) in favor of Spree::Config.tax_adjuster_class.


    • Removed deprecated method Promotion#expired? in favor of Promotion#inactive?


    • Removed nested attribute helpers generate_template, generate_html, and remove_nested. Also removes some javascript bound to selectors .remove, a[id*=nested].

    • Removed accept_alert and dismiss_alert from CapybaraExt. accept_alert is now a capybara builtin (that we were overriding) and dismiss_alert can be replaced with dismiss_prompt.

    • Removed deprecated delegate_belongs_to

Solidus 2.0.0 (2016-09-26)

  • Upgrade to rails 5.0

Solidus 1.4.1 (2017-06-08)

  • Fix syntax error in app/views/spree/admin/reimbursements/edit.html.erb #1991 (acreilly)

Solidus 1.4.0 (2016-09-26)

  • Use in-memory objects in OrderUpdater and related areas.

    Solidus now uses in-memory data for updating orders in and around OrderUpdater. E.g. if an order already has order.line_items loaded into memory when OrderUpdater is run then it will use that information rather than requerying the database for it. This should help performance and makes some upcoming refactoring easier.

    Warning: If you bypass ActiveRecord while making updates to your orders you run the risk of generating invalid data. Example:

    order.line_items.update_all(price: ...)

    Will now result in incorrect calculations in OrderUpdater because the line items will not be refetched.

    In particular, when creating adjustments, you should always create the adjustment using the adjustable relationship.

    Good example:

    line_item.adjustments.create!(source: tax_rate, ...)

    Bad examples:

    tax_rate.adjustments.create!(adjustable: line_item, ...)
    Spree::Adjustment.create!(adjustable: line_item, source: tax_rate, ...)

    We try to detect the latter examples and repair the in-memory objects (with a deprecation warning) but you should ensure that your code is keeping the adjustable's in-memory associations up to date. Custom promotion actions are an area likely to have this issue.

  • Make some 'wallet' behavior configurable

    NOTE: Order#persist_user_credit_card has been renamed to Order#add_payment_sources_to_wallet. If you are overriding persist_user_credit_card you need to update your code.

    The following extension points have been added for customizing 'wallet' behavior.

    • Spree::Config.add_payment_sources_to_wallet_class
    • Spree::Config.default_payment_builder_class

  • Backend: UI, Remove icons from buttons and tabs

  • Backend: Deprecate args/options that add icons to buttons

  • Update Rules::Taxon/Product handling of invalid match policies

    Rules::Taxon and Rules::Product now require valid match_policy values. Please ensure that all your Taxon and Product Rules have valid match_policy values.

  • Fix default value for Spree::Promotion::Rules::Taxon preferred_match_policy.

    Previously this was defaulting to nil, which was sometimes interpreted as 'none'.

  • Deprecate Spree::Shipment#address (column renamed)

    Spree::Shipment#address was not actually being used for anything in particular, so the association has been deprecated and delegated to Spree::Order#ship_address instead. The database column has been renamed spree_shipments.deprecated_address_id.

  • Coupon code application has been separated from the Continue button on the Payment checkout page

    • JavaScript for it has been moved from address.js into its own spree/frontend/checkout/coupon-code
    • Numerous small nuisances have been fixed #1090
  • Allow filtering orders by store when multiple stores are present. #1149

  • Remove unused user_id column from PromotionRule. #1259

  • Removed "Clear cache" button from the admin #1275

  • Adjustments and totals are no longer updated when saving a Shipment or LineItem.

    Previously adjustments and total columns were updated after saving a Shipment or LineItem. This was unnecessary since it didn't update the order totals, and running order.update! would recalculate the adjustments and totals again.

Solidus 1.3.0 (2016-06-22)

  • Order now requires a store_id in validations

    All orders created since Spree v2.4 should have a store assigned. A migration exists to assign all orders without a store to the default store.

    If you are seeing spec failures related to this, you may have to add let!(:store) { create(:store) } to some test cases.

  • Deprecate Spree::TaxRate.adjust, remove Spree::TaxRate.match

    The functionality of Spree::TaxRate.adjust is now contained in the new Spree::Tax::OrderAdjuster class.

    Wherever you called Spree::TaxRate.adjust(items, order_tax_zone), instead call!.

    Spree::TaxRate.match was an implementation detail of Spree::TaxRate.adjust. It has been removed, and its functionality is now contained in the private method Spree::Tax::TaxHelpers#applicable_rates(order).

  • Allow more options than current_currency to select prices

    Previously, availability of products/variants, caching and pricing was dependent only on a current_currency string. This has been changed to a current_pricing_options object. For now, this object (Spree::Variant::PricingOptions) only holds the currency. It is used for caching instead of the deprecated current_currency helper.

    Additionally, your pricing can be customized using a VariantPriceSelector object, a default implementation of which can be found in Spree::Variant::PriceSelector. It is responsible for finding the right price for variant, be it for front-end display or for adding it to the cart. You can set it through the new Spree::Config.variant_price_selector_class setting. This class also knows which PricingOptions class it cooperates with.

    Deprecated methods:

    • current_currency helper
    • Spree::Variant#categorise_variants_from_option
    • Spree::Variant#variants_and_option_values (Use Spree::Variant#variants_and_option_values#for instead)
    • Spree::Core::Search::Base#current_currency
    • Spree::Core::Search::Base#current_currency=

    Extracted Functionality:

    There was a strange way of setting prices for line items depending on additional attributes being present on the line item (gift_wrap: true, for example). It also needed Spree::Variant to be patched with methods like Spree::Variant#gift_wrap_price_modifier_in and is generally deemed a non-preferred way of modifying pricing. This functionality has now been moved into a Gem of its own to ease the transition to the new Variant::PriceSelector system.

  • Respect Spree::Store#default_currency

    Previously, the current_currency helper in both the core and api gems would always return the globally configured default currency rather than the current store's one. With Solidus 1.3, we respect that setting without having to install the spree_multi_domain extension.

  • Persist tax estimations on shipping rates

    Previously, shipping rate taxes were calculated on the fly every time a shipping rate would be displayed. Now, shipping rate taxes are stored on a dedicated table to look up.

    There is a new model Spree::ShippingRateTax where the taxes are stored, and a new Spree::Tax::ShippingRateTaxer that builds those taxes from within Spree::Stock::Estimator.

    The shipping rate taxer class can be exchanged for a custom estimator class using the new Spree::Appconfiguration.shipping_rate_taxer_class preference.

    In order to convert your historical shipping rate taxation data, please run rake solidus:upgrade:one_point_three - this will create persisted taxation notes for historical shipping rates. Be aware though that these taxation notes are estimations and should not be used for accounting purposes.

  • Deprecate setting a line item's currency by hand

    Previously, a line item's currency could be set directly, and differently from the line item's order's currency. This would result in an error. It still does, but is also now explicitly deprecated. In the future, we might delete the line item's currency column and just delegate to the line item's order.

  • Taxes for carts now configurable via the Spree::Store object

    In VAT countries, carts (orders without addresses) have to be shown with adjustments for the country whose taxes the cart's prices supposedly include. This might differ from Spree::Store to Spree::Store. We're introducting the cart_tax_country_iso setting on Spree::Store for this purpose.

    Previously the setting for what country any prices include Spree::Zone.default_tax. That, however, would also implicitly tag all prices in Spree as including the taxes from that zone. Introducing the cart tax setting on Spree::Store relieves that boolean of some of its responsibilities.

  • Make Spree::Product#prices association return all prices

    Previously, only non-master variant prices would have been returned here. Now, we get all the prices, including those from the master variant.

  • Changes to Spree::Stock::Estimator

    • The package passed to Spree::Stock::Estimator#shipping_rates must have its shipment assigned and that shipment must have its order assigned. This is needed for some upcoming tax work in to calculate taxes correctly.
    • no longer accepts an order argument. The order will be fetched from the shipment.

  • Removed Spree::Stock::Coordinator#packages from the public interface.

    This will allow us to refactor more easily.

  • Removed pre_tax_amount column from line item and shipment tables

    This column was previously used as a caching column in the process of calculating VATs. Its value should have been (but wasn't) always the same as discounted_amount - included_tax_total. It's been replaced with a method that does just that. #941

  • Renamed return item pre_tax_amount column to amount

    The naming and functioning of this column was inconsistent with how shipments and line items work: In those models, the base from which we calculate everything is the amount. The ReturnItem now works just like a line item.

    Usability-wise, this change entails that for VAT countries, when creating a refund for an order including VAT, you now have to enter the amount you want to refund including VAT. This is what a backend user working with prices including tax would expect.

    For a non-VAT store, nothing changes except for the form field name, which now says Amount instead of Pre-tax-amount. You might want to adjust the i18n translation here, depending on your circumstances. #706

  • Removed Spree::BaseHelper#gem_available? and Spree::BaseHelper#current_spree_page?

    Both these methods were untested and not appropriate code to be in core. If you need these methods please pull them into your app. #710.

  • Fixed a bug where toggling 'show only complete order' on/off was not showing all orders. #749

  • ffaker has been updated to version 2.x

    This version changes the namespace from Faker:: to FFaker::

  • versioncake has been updated to version 3.x

    This version uses a rack middleware to determine the version, uses a different header name, and has some configuration changes.

    You probably need to add this to your controller specs.

    More information is available in the VersionCake README

  • Bootstrap 4.0.0-alpha.2 is included into the admin.

  • Pagination now uses an admin-specific kaminari theme, which uses the bootstrap4 styles. If you have a custom admin page with pagination you can use this style with the following.

    <%= paginate @collection, theme: "solidus_admin" %>
  • Settings configuration menu has been replaced with groups of tabs at the top

    • Settings pages were grouped into related partials as outlined in #634
    • Partials are rendered on pages owned by the partials as tabs as a top bar
    • Admin-nav has a sub-menu for the settings now
  • Lists of classes in configuration (config.spree.calculators, spree.spree.calculators, etc.) are now stored internally as strings and constantized when accessed. This allows these classes to be reloaded in development mode and loaded later in the boot process. #1203

Solidus 1.2.0 (2016-01-26)

  • Admin menu has been moved from top of the page to the left side.

    • Submenu items are accessible from any page. See the wiki for more information and instructions on upgrading.
    • Solidus_auth_devise should be updated to '~> 1.3' to support the new menu.
    • Added optional styles to the admin area to advance admin rebrand. To use the new colors, add @import 'spree/backend/themes/blue_steel/globals/_variables_override'; to your spree/backend/globals/variables_override.
  • Removed deface requirement from core

    Projects and extensions which rely on deface will need to add it explicitly to their dependencies.

  • testing_support/capybara_ext.rb no longer changes capybara's matching mode to :prefer_exact, and instead uses capybara's default, :smart.

    You can restore the old behaviour (not recommended) by adding Capybara.match = :prefer_exact to your spec_helper.rb.

    More information can be found in capybara's README

  • Fixed a bug where sorting in the admin would not save positions correctly. #632

  • Included (VAT-style) taxes, will be considered applicable if they are inside the default tax zone, rather than just when they are the defaut tax zone. #657

  • Update jQuery.payment to v1.3.2 (from 1.0) #608

  • Removed Order::CurrencyUpdater. #635

  • Removed Product#set_master_variant_defaults, which was unnecessary since master is build with is_master already true.

  • Improved performance of stock packaging #550 #565 #574

  • Replaced admin taxon management interface #569

  • Fix logic around raising InsufficientStock when creating shipments. #566

    Previously, InsufficientStock was raised if any StockLocations were fully out of inventory. This was incorrect because it was possible other stock locations could have fulfilled the inventory. This was also incorrect because the stock location could have some, but insufficient inventory, and not raise the exception (an incomplete package would be returned). Now the coordinator checks that the package is complete and raises InsufficientStock if it is incomplete for any reason.

  • Removed #627 Use the "GlobalZone" factory instead: FactoryGirl.create(:global_zone)

Solidus 1.1.0 (2015-11-25)

  • Address is immutable (Address#readonly? is always true)

    This allows us to minimize cloning addresses, while still ensuring historical data is preserved.

  • UserAddressBook module added to manage a user's multiple addresses

  • GET /admin/search/users searches all of a user's addresses, not just current bill and ship addresss

  • Adjustment state column has been replaced with a finalized boolean column. This includes a migration replacing the column, which may cause some downtime for large stores.

  • Handlebars templates in the admin are now stored in assets and precompiled with the rest of the admin js.

  • Removed map_nested_attributes_keys from the Api::BaseController. This method was only used in one place and was oblivious of strong_params.

  • Change all mails deliveries to #deliver_later. Emails will now be sent in the background if you configure active_job to do so. See the rails guides for more information.

  • Cartons deliveries now send one email per-order, instead of one per-carton. This allows setting @order and @store correctly for the template. For most stores, which don't combine multiple orders into a carton, this will behave the same.

  • Some HABTM associations have been converted to HMT associations. Referential integrity has also been added as well. Specifically:

    • Prototype <=> Taxon
    • ShippingMethod <=> Zone
    • Product <=> PromotionRule

Solidus 1.0.1 (2015-08-19)


Solidus 1.0.0 (2015-08-11)