如何从已安装的 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
吗?
我 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
吗?