我在我的应用程序中使用 Rails 引擎作为 gem。引擎有PostsController
使用多种方法,我想在我的主应用程序中扩展 Controller 逻辑,例如添加一些方法。如果我只是创建 PostsController
在主应用程序中,则未加载引擎的 Controller 。
问题中提出了一个解决方案Rails engines extending functionality基于更改 ActiveSupport::Dependencies#require_or_load
这是唯一/正确的方法吗?如果是,我把那段代码放在哪里?
编辑1:
这是代码suggested by Andrius用于 Rails 2.x
module ActiveSupport::Dependencies
alias_method :require_or_load_without_multiple, :require_or_load
def require_or_load(file_name, const_path = nil)
if file_name.starts_with?(RAILS_ROOT + '/app')
relative_name = file_name.gsub(RAILS_ROOT, '')
@engine_paths ||= Rails::Initializer.new(Rails.configuration).plugin_loader.engines.collect {|plugin| plugin.directory }
@engine_paths.each do |path|
engine_file = File.join(path, relative_name)
require_or_load_without_multiple(engine_file, const_path) if File.file?(engine_file)
end
end
require_or_load_without_multiple(file_name, const_path)
end
end
最佳答案
按照设计,Rails::Engine 中的类应该限定为引擎。这样他们就不会通过意外踩踏主应用程序或其他引擎中加载的所有代码来引入奇怪的错误。 Monkeypatching ActiveSupport::Dependencies 来全面混合引擎是一个非常糟糕的解决方法。
只需使用 Rails::Railtie 即可。它们具有所有相同的功能,但与引擎的范围不同。您可以访问整个 rails 应用程序堆栈(包括引擎)。这是一种更外科手术的方法。
module MyModule
module SomeModelExtensions
# Called when this module is included on the given class.
def self.included(base)
base.send(:include, InstanceMethods)
base.extend(ClassMethods)
end
module ClassMethods
def some_new_class_method
# do stuff...
end
end
module InstanceMethods
def some_new_instance_method
# do stuff...
end
end
end
module SomeControllerExtensions
def self.included(base)
base.send(:include, InstanceMethods)
base.alias_method_chain :new, :my_module
end
module InstanceMethods
# override the 'new' method
def new_with_my_module
# do stuff
end
end
end
class Railtie < ::Rails::Railtie
# The block you pass to this method will run for every request in
# development mode, but only once in production.
config.to_prepare do
SomeModel.send(:include, MyModule::SomeModelExtensions)
SomeController.send(:include, MyModule::SomeControllerExtensions)
end
end
end
就文件布局而言,railties 看起来与引擎完全一样。
进一步阅读:Extending Rails 3 with Railties
如果您仍然感到困惑,请查看这个具有完整实现的 git 项目:https://github.com/jamezilla/bcms_pubcookie
关于ruby-on-rails - 在主应用程序中扩展 Rails 3 引擎的 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5045068/