Spree::AppConfiguration
class has a list of all the service object classes that can be natively customized. Look for through the source code of that class and see if there's an option that resembles what you need to do. If yes, bingo!Spree::AppConfiguration
is not the only configuration class that contains service objects. Before resorting to other customization methods, search through Solidus' source code and see if there are any other options that allow you to replace the class you need.Spree::OrderMerger
class to understand what public API Solidus expects us to implement in our custom version:#initialize
, which accepts an order.#merge!
, which accepts another order to merge with the first one and (optionally) the current user.Spree::Order#finalize!
method to do it, but what if the implementation changes and the finalization logic is moved somewhere else? With the event bus, you can ask Solidus to run your custom logic whenever an order is finalized, without having to know about the platform's internals.OrderNotificationSubscriber
module that looks like this:.spree
suffix. Otherwise, you will subscribe to Rails' native events as well! When subscribing to a specific event, the event name is normalized automatically, so the suffix can be omitted.Spree::Product
already has an #available?
method to control a product's visibility. This is the original implementation:Module#prepend
. If you're not familiar with it, #prepend
is a method that allows us to insert a module at the beginning of another module's ancestors chain. Think of it as taking a module A and placing it "in front" of another module B: when you call a method on module B, Ruby will first hit module A and then continue down the chain of ancestors.#class_eval
for overrides, but #prepend
is a cleaner and more easily maintainable approach. You may see old guides, tutorials and extensions still using #class_eval
, but you should know this is a deprecated pattern.prepend
is called, then Rails might not be able to include the prepended behavior. This might happen if you're prepending a views helper or an ActiveSupport concern. For these cases, you might have no choice but to use #class_eval
to override the module. For more information, please see Module.prepend does not work nicely with included modules.Spree::Product#available?
method by writing a module that will be prepended to Spree::Product
. In the Solidus ecosystem, we call such modules overrides. Overrides are usually named in a descriptive way, that expresses how the override extends the original class.AddGlobalHiddenFlag
override for Spree::Product
:#available?
implementation, but we can also call the original implementation with super
. This allows you to decide whether you want to extend the original method or completely override it.