0

分離された Rails Engine があります: Admin.

そのエンジンではSites、GUI を使用して作成します。

エンジン内:

module Admin
  class Site < ActiveRecord::Base
  end
end

Siteメイン アプリでは、ルート レベルで定数として使用するために、エンジンから継承します。

class Site < Admin::Site
end

Admin::Siteこれを行うのは、メイン アプリのモデル、コントローラー、およびテストを結合するのが間違っていると感じるからです。しかし、このアプローチにはいくつかの欠点があり、カップリングは同じであると主張する人もいると思います.

これを継承よりも良い方法で委任するにはどうすればよいですか?

また

コードを再構築Siteして、メイン アプリとエンジンの両方が使用できる gem にクラスを配置する必要がありますか? 私が本当に望んでいるのは、エンジンのクラスへのインターフェースで、エントリ ポイントを減らし、結合を減らすことです。

補足として、これらのクラスは全部で 3 ~ 4 個あります。これらのクラスはエンジンに常駐していますが、メイン アプリで使用されています。

編集:

たぶん、次のようにラップする必要があります。

class Site 
  def initialize(args = {})
    @klass = Admin::Site.new(args)    
  end

  def method_missing(method_name, *args, &block)
    @klass.send(method_name, *args, &block)
  end
end

もちろん、インターフェイスを絞り込んで、Site必要なものだけをAdmin::Siteメイン アプリに含めることもできます。

4

1 に答える 1

1

1) ActiveSupport
::Conern
2) オープン クラス

これらの 3 ~ 4 個のモデル/コントローラーをエンジンに分離した場合、1 つのアプローチは、ActiveSupport::Concernを活用してエンジンの機能を MainApp に明示的に含めることです。

詳細はこちらActiveSupport::Concern の Rails Docs

ActiveSupport::懸念の例:

# Rails Engine
module SomeEngine
  module SomeController

    extend ActiveSupprt::Concern

    included do
      before_filter :some_before_filter
    end

    # regular instance methods
    def index 
      ...
    end

    protected
    def some_before_filter
      ....
    end

  end
end    

# MainApp
class SomeController < BaseController
  include SomeEngine::SomeController

  # rest of MainApp logic
end

もう 1 つの一般的なアプローチは、Ruby クラスのメソッドを実行時に書き換える (「オープン クラス化」) ことです。Spreeは、MainApp のエンジン モデル/コントローラー クラスに「デコレーター」パターンを実装することでこれを行います。

詳細はこちら、シュプレーのデコレータの実装

「#class_eval do」の例、

# in MainApp
SomeEngine::SomeController.class_eval do
  # logic added in the MainApp
end

また、RailsEngnes に関する RailsConf の講演 (
http://confreaks.com/videos/863-railsconf2012-rails-engines-patterns ) もチェックします。

于 2012-12-10T00:56:02.910 に答える