【问题标题】:How can I extend my controller from installed Spree gem's controller?如何从已安装的 Spree gem 的控制器中扩展我的控制器?
【发布时间】:2021-01-09 03:48:59
【问题描述】:

我已经成功安装了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 的控制器中扩展我的控制器?

【问题讨论】:

  • 类 ApplicationController
  • 嘿,谢谢您的回复。但它不起作用:(

标签: ruby-on-rails ruby spree spree-auth-devise


【解决方案1】:

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

以另一种方式声明它们以及会创建一个循环依赖,结果类加载失败。在不改变 Spree 本身的情况下,唯一的解决办法是做其他事情。

相反,要让您的控制器使用 Spree::BaseController 作为超类,首先以更常用的方式定义 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,因此您需要在创建后修改它们.

【讨论】:

  • 和我的意思一样,但描述得更好:) 很好的调查
【解决方案2】:

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

我建议您使用另一种方法来创建一个新的 Base 控制器类,然后从中继承所有子类并将 ApplicationController 留给基本导轨

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 继承我的控制器,看看我的问题。当我从Spree:: BaseController 继承时,我得到uninitialized constant Spree::BaseController (NameError) 错误。
  • 是的,因为 ApplicationController 由 Rails 内部使用,当 Rails 尝试访问它时,您会收到未定义的错误。但是,如果您使用自己的自定义控制器,Rails 内部无法访问这些控制器,错误就会消失。我测试了下面的例子,没问题。我只是想确定一下,没有特定情况可以更改 Rails 的继承ApplicationController
【解决方案3】:

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

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

【讨论】:

  • 您好,感谢您的回复。在base_controller 中有大量的助手,包括其他控制器。我无法复制和粘贴所有内容。这不是正确的方法。有什么想法吗?
【解决方案4】:

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

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,
...

我正在使用

  • 红宝石 2.6.5
  • 导轨 6.0.3.4
  • 在 Gemfile 中添加您的狂欢宝石后运行 bundle update

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    • 2012-01-29
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多