0

我有一个独立的 Rails 引擎: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 个模型/控制器隔离在一个引擎中,一种方法是利用ActiveSupport::Concern将引擎的功能明确包含在 MainApp 中。

更多信息,ActiveSupport::Concern 上的 Rails 文档

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

另一种常见的方法是在运行时重写一个 Ruby 类方法(“开放类”)Spree通过在 MainApp 中为 Engine 模型/控制器类实现“装饰器”模式来做到这一点。

更多信息在这里,Spree 对装饰器的实现

“#class_eval 做”示例,

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

我还会查看 RailsConf 的 RailsEngnes 演讲,
http: //confreaks.com/videos/863-railsconf2012-rails-engines-patterns

于 2012-12-10T00:56:02.910 回答