Spree module decorator
Asked Answered
K

3

6

I'm using Spree Commerce for my Online Shop. I want to change some behaviour during the checkout process, that is defined in app/models/spree/order/checkout.rb inside the spree gem. So I made a checkout_decorator.rb at the same point in my application.

The problem is, that my changes aren't loaded. And another problem is, that everything inside the module is inside one method, the def self.included(klass) method. So I think I have to overwrite the whole file, instead of just one method. Here is what my decorator looks like:

checkout_decorator.rb

Spree::Order::Checkout.module_eval do
  def self.included(klass)
    klass.class_eval do
      class_attribute :next_event_transitions
      class_attribute :previous_states
      class_attribute :checkout_flow
      class_attribute :checkout_steps

      def self.define_state_machine!
         # here i want to make some changes
      end

      # and the other methods are also include here
      # for readability, i don't show them here
    end
  end
end

The original file checkout.rb from the spree gem looks like this:

module Spree
  class Order < ActiveRecord::Base
    module Checkout
      def self.included(klass)
        klass.class_eval do
          class_attribute :next_event_transitions
          class_attribute :previous_states
          class_attribute :checkout_flow
          class_attribute :checkout_steps

          def self.checkout_flow(&block)
            if block_given?
              @checkout_flow = block
              define_state_machine!
            else
              @checkout_flow
            end
          end

          def self.define_state_machine!
             # some code
          end

          # and other methods that are not shown here
        end
      end
    end
  end
end

So my questions are: Why does this not work? Is module_eval the right way to do this? I tried class_eval but it doesn't work either. How can I solve this?

Kingpin answered 23/7, 2013 at 12:42 Comment(0)
D
1

The module_eval method isn't going to work for you.

You should look at the Spree Checkout Flow Documentation for some good examples on how to customize the checkout flow. This is the recommended way for customizing the checkout flow as you won't need to copy/paste a whole bunch of code.

Diehard answered 23/7, 2013 at 15:57 Comment(0)
A
1

The namespacing isn't right.

Try Spree::Order::Checkout.class_eval do

Atheist answered 11/2, 2016 at 10:23 Comment(0)
T
0

tl;dr: Overwrite the method you want in the Spree::Order class instead of the Spree::Order::Checkout module.

You mentioned that in the original file (spree_core-3.2.0.rc3/app/models/spree/order/checkout.rb) there's a method wrapping the entire module.

def self.included(klass)
  klass.class_eval do

This method is called when the module is included in a class, and does its own class_eval to add the module's methods to instances of the class including it.

So since (spree_core-3.2.0.rc3/app/models/spree/order.rb) has this line:

include Spree::Order::Checkout

We can add a decorator to the order class itself (app/models/spree/order_decorator.rb)

Tedium answered 19/5, 2017 at 17:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.