我有一个引擎,它定义了一些模型和控制器。我希望能够在我的应用程序中扩展某些模型/控制器的功能(例如添加方法),而不会从引擎中丢失原始模型/控制器功能。在我读到的任何地方,您只需要在应用程序中定义具有相同名称的控制器,Rails将自动合并它们,但它对我不起作用并且引擎中的控制器被简单地忽略(我不认为它甚至被加载)。
答案 0 :(得分:18)
require MyEngine::Engine.root.join('app', 'models', 'my_engine', 'my_model')
在应用程序中的模型类定义之前。
答案 1 :(得分:8)
您可以将这些行添加到lib根目录中的引擎模块文件中:
def self.root
File.expand_path(File.dirname(File.dirname(__FILE__)))
end
def self.models_dir
"#{root}/app/models"
end
def self.controllers_dir
"#{root}/app/controllers"
end
然后您可以在主应用程序(使用引擎的应用程序)中从引擎中获取必要的文件。这很好,因为你维护了Rails Engines的默认功能,并且还有一个简单的工具来使用普通的ruby继承,而不需要修补。
EX:
#ENGINE Model -
class User < ActiveRecord::Base
def testing_engine
puts "Engine Method"
end
end
#MAIN APP Model -
require "#{MyEngine.models_dir}/user"
class User
def testing_main_app
puts "Main App Method"
end
end
#From the Main apps console
user = User.new
puts user.testing_engine #=> "Engine Method"
puts user.tesing_main_app #=> "Main App Method"
答案 2 :(得分:2)
如果其他人在将来的某个时间遇到同样的问题,这就是我写的代码解决了我的问题:
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
如果文件路径以'app'开头,这将自动要求来自引擎的文件。
答案 3 :(得分:1)
这是事实。首先使用的控制器将被使用。
为了使其有效,您可能有两种选择:
希望这有帮助。
答案 4 :(得分:1)
您可以更改引擎的加载顺序,以避免每个模型的要求。
在config / application.rb中添加以下行:
module MyApp
class Application
config.railties_order = [MyEngine::Engine, :main_app, :all]
end
end
这将确保在MyApp
之前加载MyEngine中的模型答案 5 :(得分:0)
我之前从未使用过引擎,但是你不能定义一个从引擎提供的控制器继承的新控制器