簡體   English   中英

Rails引擎擴展功能

[英]Rails engines extending functionality

我有一個定義一些模型和控制器的引擎。 我希望能夠在我的應用程序中擴展某些模型/控制器的功能(例如添加方法),而不會從引擎中丟失原始模型/控制器功能。 在我讀到的任何地方,您只需要在應用程序中定義具有相同名稱的控制器,Rails將自動合並它們,但它對我不起作用並且引擎中的控制器被簡單地忽略(我不認為它甚至被加載)。

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

在應用程序中的模型類定義之前。

您可以將這些行添加到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"

如果其他人在將來的某個時間遇到同樣的問題,這就是我編寫的修復我的問題的代碼:

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”開頭,這將自動要求應用程序中的文件。

您可以更改引擎的加載順序,以避免每個模型的要求。

在config / application.rb中添加以下行:

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

這將確保在MyApp之前加載MyEngine中的模型

那是真實的。 將使用首先找到的控制器。

因此,要使其工作,您可能有兩個選擇:

  • 創建控制器的本地副本,並修改所需的方法
  • 如果你可以控制插件,你可以創建一個包含代碼的模塊,並在兩個控制器中包含代碼,只覆蓋本地控制器中的方法。 據我所知,由於沒有多重繼承,這是唯一的方法。

希望這可以幫助。

我之前從未使用過Engines,但是你不能定義一個繼承自引擎提供的控制器的新控制器

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM