如何从已安装的 Spree gem 的控制器扩展我的控制器?

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

spree gem 安装成功。我不需要 spree_frontend。这是 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'

所以我想从 Spree's BaseController 扩展我的 ApplicationController。这是代码:

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

但我收到以下错误:

uninitialized constant Spree::BaseController (NameError)

如何从已安装的 Spree gem 的控制器扩展我的控制器?

如错误所述,Spree::BaseController 未在您的应用中定义 - 它在 spree-core gem 中定义。如果您在本地重新创建基本控制器的文件路径,即 app/controllers/spree/,并将代码从控制器复制并粘贴到本地 base_controller.rb,您可以编辑它并添加自定义功能。

请注意,它仍将继承自 ApplicationController,但您可以将要放入 ApplicationController 的任何代码放入此处,并让您的 类 继承自Spree::BaseContoller 效果一样

有什么理由需要严格扩展 ApplicationController

我建议您使用另一种方法来创建一个新的 Base 控制器 class,然后继承它的所有子控制器并将 ApplicationController 留给 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

您 运行 遇到的问题是 Spree::BaseController 已经继承自 ApplicationController;参见 https://github.com/spree/spree/blob/master/core/app/controllers/spree/base_controller.rb。这是为了让您的 ApplicationController 在 Spree 看到之前定义 current_user 和类似的基本功能。

以相反的方式声明它们 以及 创建循环依赖,结果 class 加载失败。在不更改 Spree 本身的情况下,唯一的解决方法是做其他事情。

相反,要让您的控制器将 Spree::BaseController 用作超级 class,请首先以更常见的方式定义 ApplicationController,例如:

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

然后发明一个新的抽象控制器,供您自己使用,它继承自 Spree,例如我们将其命名为 StoreBaseController:

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

现在可以在定义更具体的控制器时使用 StoreBaseController 代替 ApplicationController。它起作用是因为它不会在继承树中创建循环,现在看起来像这样:

注意:如果您还使用 rails generator 命令从模板生成控制器或脚手架,请注意生成器已 ApplicationController 在模板中进行硬编码,因此您将创建后需要修改它们。

嗯嗯,我试过你想做的但我成功了(?)

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

在控制台中

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

我正在使用

  • ruby 2.6.5
  • rails6.0.3.4
  • 运行 bundle update 在 Gemfile 中添加您的狂欢宝石后

所以我认为这是需要或自动加载的问题

  • 你的 rails 版本是什么? 6? spree >= 4.1 应该使用 rails >= 6
  • Spree::BaseController 是否存在于 rails 控制台中?
  • Bundler.require(*Rails.groups)config/application.rb吗?
  • gem 是否包含在 Gemfile 的正确组中?例如:狂欢宝石在 :production 组中。
  • config/application.rb中有config.load_defaults 6.0吗?