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 Engine の既定の機能を維持し、パッチを適用することなく、通常の 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

それは本当です。最初に見つかったコントローラが使用されます。

したがって、それを機能させるには、次の 2 つのオプションがあります。

  • コントローラーのローカル コピーを作成し、必要なメソッドを変更します。
  • プラグインを制御できる場合は、コードを含むモジュールを作成し両方のコントローラーにコードを含めて、ローカル コントローラーのメソッドのみをオーバーライドすることができます。私によると、多重継承はないので、それが唯一の方法です。

お役に立てれば。

于 2010-06-03T10:14:25.303 に答える
0

エンジンを使ったことがないのですが、エンジンが提供するコントローラーを継承する新しいコントローラーを定義できませんか

于 2010-06-03T10:51:31.967 に答える