简体   繁体   中英

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

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?

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 eg:

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

then invent a new abstract controller, for your own use, that inherits from Spree, eg 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:

控制器层次结构

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.

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

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.

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 ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM