2

I have spree gem installed successfully. I don't need spree_frontend. Here is the Gemfile

gem 'spree_core', '4.2.0.rc2'
gem 'spree_backend', '4.2.0.rc2'
gem 'spree_sample', '4.2.0.rc2'
gem 'spree_cmd', '4.2.0.rc2'
gem 'spree_auth_devise', '~> 4.2'

So I want to extend my ApplicationController from Spree's BaseController. Here is the code:

class ApplicationController < Spree::BaseController
  include Spree::Core::ControllerHelpers::Order
end

But I get following errors:

uninitialized constant Spree::BaseController (NameError)

How can I extend my controller from installed Spree gem's controller?

Zeck
  • 6,433
  • 21
  • 71
  • 111

4 Answers4

5

The problem you're running into is that Spree::BaseController already inherits from ApplicationController; see https://github.com/spree/spree/blob/master/core/app/controllers/spree/base_controller.rb. This is to allow your ApplicationController to define things like current_user and similar basic functions before Spree sees it.

Declaring them the other way around as well creates a circular dependency, and the class loading fails as a result. Without changing Spree itself, the only fix is to do something else.

Instead, to have your controllers use Spree::BaseController as a superclass, first define ApplicationController in the more usual fashion e.g.:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # ...
end

then invent a new abstract controller, for your own use, that inherits from Spree, e.g. let's name it StoreBaseController:

# app/controllers/store_base_controller.rb
class StoreBaseController < Spree::BaseController
  include Spree::Core::ControllerHelpers::Order
  # ...
end

This StoreBaseController can now be used in place of ApplicationController when defining more specific controllers. It works because it doesn't create a loop in the inheritance tree, which now looks like this:

Controller Hierarchy

Note: if you're also using the rails generator command to produce controllers or scaffolds from templates, be aware that the generator has ApplicationController hard-coded in the templates, so you'll need to amend them once created.

inopinatus
  • 3,597
  • 1
  • 26
  • 38
1

Is there any reason why you need to extend strictly ApplicationController?

I advise you alternative approach to create a new Base controller class, and then inherit all the children from it and leave ApplicationController to basic rails

app/controller/my_base_controller.rb

class MyBaseController < Spree::BaseController
  def foo
    # ...
  end
end

app/controller/my_resources_controller.rb

class MyResourcesController < MyBaseController
  def bar
    # ...
  end
end
zhisme
  • 2,368
  • 2
  • 19
  • 28
  • Hey thanks for reply. It's just example. My problem is I can't inherit my controller from `Spree::BaseController` See take a look at my question. When I inherit from `Spree:: BaseController` I get `uninitialized constant Spree::BaseController (NameError)` errors. – Zeck Jan 14 '21 at 03:42
  • yes, because `ApplicationController` used internally by Rails, and while Rails trying to access it, you get undefined error. However if you fall down to your own custom controllers, that are not accessed by Rails internally, the error will be gone. I tested the following example, and it is ok. I just wanted to be sure, that there is no specific case to change inheritance for Rails `ApplicationController` – zhisme Jan 14 '21 at 07:50
0

As the errors states, Spree::BaseController is not defined within your app - it is defined in the spree-core gem. If you re-create the filepath to the base controller locally, that is app/controllers/spree/, and copy and paste the code from the controller into a local base_controller.rb, you can edit it and add custom functionality.

Note that it will still inherit from the ApplicationController, but you can place any of the code you wanted to put in the ApplicationController into here and have your classes inherit from Spree::BaseContoller and the effect will be the same.

kykyi
  • 375
  • 4
  • 10
  • Hi, thank you for reply. In `base_controller` there are tons of helpers, other controllers included. I can't copy and paste all of it. It's not a right way. Any idea? – Zeck Jan 11 '21 at 03:16
-1

hmmm, I tried what you want to do but I succeeded (?)

class PagesController < Spree::BaseController
  include Spree::Core::ControllerHelpers::Order
end

in the console

2.6.5 :006 > pp PagesController.ancestors
[PagesController,
 Spree::Core::ControllerHelpers::Order,
 #<Module:0x00007fca27610410>,
 Spree::BaseController,
 Spree::Core::ControllerHelpers::CurrencyHelpers,
 Spree::Core::ControllerHelpers::StrongParameters,
...

I'm using

  • ruby 2.6.5
  • rails 6.0.3.4
  • run bundle update after adding the your spree's gems in the Gemfile

So I think its the requiring or auto-loading problem

  • what's your rails version? 6? spree >= 4.1 should use rails >= 6
  • Does Spree::BaseController exist in rails console?
  • Is Bundler.require(*Rails.groups) in config/application.rb?
  • Does the gems included in the right group of the Gemfile? ex: spree gems are in :production group.
  • Does it have config.load_defaults 6.0 in config/application.rb?
kevinluo201
  • 1,444
  • 14
  • 18