15

我有一个定义一些模型和控制器的引擎。我希望能够在我的应用程序中扩展某些模型/控制器的功能(例如添加方法),而不会丢失引擎的原始模型/控制器功能。在我读到的所有地方,您只需要在应用程序中定义具有相同名称的控制器,Rails 会自动合并它们,但是它对我不起作用,并且引擎中的控制器被简单地忽略(我认为它甚至没有加载)。

4

6 回答 6

19
require MyEngine::Engine.root.join('app', 'models', 'my_engine', 'my_model')

在应用程序中的模型类定义之前。

于 2011-03-15T07:51:13.883 回答
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 引擎的默认功能,并且还有一个简单的工具可以使用普通的 ruby​​ 继承,而无需打补丁。

前任:

#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"
于 2011-02-23T20:43:13.613 回答
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”开头,这将在从应用程序请求之前自动从引擎请求文件。

于 2010-06-07T14:53:47.947 回答
1

那是真实的。将使用首先找到的控制器。

因此,要使其正常工作,您可能有两种选择:

  • 创建控制器的本地副本,并修改您需要的方法
  • 如果您可以控制插件,则可以创建一个包含代码的模块并将代码包含在两个控制器中,仅覆盖本地控制器中的方法。据我说,由于没有多重继承,这是唯一的方法。

希望这可以帮助。

于 2010-06-03T10:14:25.303 回答
1

您可以更改引擎的加载顺序以避免对每个模型的要求。

在 config/application.rb 添加这一行:

module MyApp
  class Application
    config.railties_order = [MyEngine::Engine, :main_app, :all]
  end
end

这将确保 MyEngine 中的模型在 MyApp 之前加载

于 2015-02-05T01:48:11.593 回答
0

我以前从未使用过引擎,但您不能定义一个继承自引擎提供的控制器的新控制器

于 2010-06-03T10:51:31.967 回答